Disclaimer: The purpose of the Open Case Studies project is to demonstrate the use of various data science methods, tools, and software in the context of messy, real-world data. A given case study does not cover all aspects of the research process, is not claiming to be the most appropriate way to analyze a given data set, and should not be used in the context of making policy decisions without external consultation from scientific experts.
This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 (CC BY-NC 3.0) United States License.
Motivation
The following papers motivated this case study.
Twenge JM, Cooper AB, Joiner TE, Duffy ME, Binau SG. Age, period, and cohort trends in mood disorder indicators and suicide-related outcomes in a nationally representative dataset, 2005-2017. J Abnorm Psychol.128,3 (2019):185-199. doi:10.1037/abn0000410
Olfson, M., Blanco, C., Wang, S., Laje, G. & Correll, C. U. National Trends in the Mental Health Care of Children, Adolescents, and Adults by Office-Based Physicians. JAMA Psychiatry. 71, 81 (2014):81-90. doi: 10.1001/jamapsychiatry.2013.3074.
The main findings of the first article are:
Rates of major depressive episode in the last year increased 52% 2005–2017 (from 8.7% to 13.2%) among adolescents aged 12 to 17 and 63% 2009–2017 (from 8.1% to 13.2%) among young adults 18–25.
Serious psychological distress in the last month and suicide-related outcomes (suicidal ideation, plans, attempts, and deaths by suicide) in the last year also increased among young adults 18–25 from 2008–2017 (with a 71% increase in serious psychological distress), with less consistent and weaker increases among adults ages 26 and over.
Cultural trends contributing to an increase in mood disorders and suicidal thoughts and behaviors since the mid-2000s, including the rise of electronic communication and digital media and declines in sleep duration, may have had a larger impact on younger people, creating a cohort effect.
While the main findings of the second article are:
Compared with adult mental health care, the mental health care of young people has increased more rapidly.
Between 1995-1998 and 2007-2010, visits resulting in mental disorder diagnoses per 100 population increased significantly faster for youths (from 7.78 to 15.30 visits) than for adults (from 23.23 to 28.48 visits) (interaction: P < .001).
Psychiatrist visits also increased significantly faster for youths (from 2.86 to 5.71 visits).
While depression appear to be on the rise for youths, youths also appear to be seeking more mental health care.
In this case study we will evaluate data related to depression episodes and mental health care to evaluate trends overtime. We will be using data from the National Survey on Drug Use and Health (NSDUH). This data was also used in the first study.
Main Questions
Our main questions:
- How have depression rates in American youth changed since 2002, according to the NSDUH data?
- Do mental health services appear to be reaching more youths? How have rates differed between different youth subgroups (gender, ethnicity)?
Learning Objectives
It may be a good idea to provide a link to Rstudio’s webpage. For the first few months using R, I did not differentiate between R and R Studio. It may be a good distinction to make at least implicitly by providing a link.
In this case study, we will determine the percent of youth in America that have had a major depressive episode in the past year since 2002. We will compare how different youth subgroups have changed over time (by age group (12-13,14-15, and 16-17), gender, ethnicity). We will especially focus on using packages and functions from the Tidyverse, such as rvest. The tidyverse is a library of packages created by RStudio. While some students may be familiar with previous R programming packages, these packages make data science in R especially efficient.

We will begin by loading the packages that we will need:
I made some modifications to the table below. The tidyverse package hyperlink referenced readr. I thought this was incorrect. I changed this to the tidyverse website and provided a different description. If this was indeed a typo, it may need to be fixed in other case studies.
| here |
to easily load and save data |
| tidyverse |
R packages for data science |
| rvest |
to scrape web pages |
The first time we use a function, we will use the :: to indicate which package we are using. Unless we have overlapping function names, this is not necessary, but we will include it here to be informative about where the functions we will use come from.
Context
According to other sources the rate of suicide has increased for most age groups in the United States over the past decade and a half.

While suicide does appear to be increasing amoung youths it also appears to be increasing amoung middle aged adults as well for both females and males.

According to the CDC:
Since 2008, suicide has ranked as the 10th leading cause of death for all ages in the United States. In 2016, suicide became the second leading cause of death among those aged 10–34 and the fourth leading cause among those aged 35–54.
So although sucide is on the rise for most age groups, sucide is one of the top two contributors to death for youths. This warrents further examination of mental health of American youths.

Limitations
Perhaps “underestimates in the p-values…” is not the correct way to phrase this. I would look for a better way to word this.
Wording for this section should be reviewed.
There are some important considerations regarding this data analysis to keep in mind:
We treat sample estimates—estimates of the true population value—as observed values. This produces understimates in the p-values of statistical tests conducted.
Furthermore, the sampling mechanism utilized can introduce selection bias in cases where the the sampling methods do not produce a representative sample.
Data is collected from human participants; this presents the potential for information bias, as there is the potential that partificipants in the sampling frame may for a variety of reasons report inaccurate information.
Data Import
Data is often made available online. Usually, the data we are interested in is made available for download on the page as a delimited text file. However, sometimes data is not made available in this manner.
How do we proceed in this scenario?
We can manually copy each cell of data, however, this process is often inefficient, subject to error, and not reproducible.
We can also use R for web scraping.
Web scraping is the process of extracting data from a website.
There are two main steps to web scraping:
Identify location of data that will be scraped
Save the webpage element to an object
We accomplish STEP 1 with our web browser.
We accomplish STEP 2 in the R programming environment.
I could not find the animation that I referred to on several occasions.
However, I was able to find the sources that I consulted to create the three step rvest process. They are included below
RStudio
Blog
The rvest package can be thought of as the pdftools package for webscraping. Upon pulling the data, additional wrangling will likely be required; but like the pdftools package, rvest streamlines the extraction process.
The two steps can be broken down even further:
- Identify location of data that will be scraped
- right-click to inspect element (webpage)
- hover pointer over components of element (webpage) until the data has been found
- copy Xpath of data sought
- Save webpage element to an object
- import html code for element (webpage)
- extract pieces (table) out of HTML documents (webpage) using Xpath
- parse the html table into a data frame
Below is a animated overview of the process.
Let’s go to the web page with all the tables we are interested in scraping.

Once on the webpage, there aren’t any visible options to download the data.
Right-click and select “Inspect”

A window opens.
This window allows us to glance at the internal mechanics of the webpage. To scrape the data from the webpage, we need to first learn a little bit about the components that make it thet web page it is.
Hovering our mouse over the elements of the webpage highlights the respective section of the webpage it represents. By hovering over several elements—and opening elements when the highlighted portion is too large—we can indentify the element that contains the data we are looking for.

Right click on the element and copy the XPath. We will need this XPath for the next step.

Now we can return to the R programming environment

I included the following line to help separate the process.
2) Save webpage element to an object
For the first question we intend to answer, the XPath is /html/body/div[4]/div[1]/table. We use this Xpath with functions from the rvest package to scrape data from the web.
I wanted to include the last slide/component of the GIF. However, I realized that the audience would also benefit from having an actual code chunk. As a result, this section may need some very minor reworking.

We need to:
- import html code for element (webpage)
- extract pieces (table) out of HTML documents (webpage) using Xpath
- parse the html table into a data frame
To do this:
- We import the html code using
rvest::read_html().
- We extract specific components of the webpage using
rvest::read_node().
- We convert this html table into a dataframe using
rvest::html_table().
The rvest package provides wrappers for the xml2 and httr packages. I was not sure whether to tag the following functions as rvest or xml2/httr. I will leave that decision to you..
Great! We have successfully scraped the data.
From here on, we will need to wrangle the data.
First, we need to repeat the above process for the other tables we are interested in.
We can create a function to accomplish this succinctly.
For some odd reason, calling the function() function with the base:: prefix causes an error.
We apply the function we created too the
Data Exploration and Wrangling
Now that we’ve imported the data, let’s see if we can wrangle a table. Since the data comes from a source that is well-maintained, it is likely that whatever steps we take to wrangle this first table will also be necessary in the wrangling of subsequent tables. This is because well-maintained data sources often format different datasets similarly. We can take advantage of this similarity to speed up the wrangling process.
Table11.1a
[1] 21 18
table11.1a <- table11.1a[-dim(table11.1a)[1],]
table11.1a <- table11.1a %>%
dplyr::na_if("nc") %>%
dplyr::na_if("--") %>%
dplyr::na_if("") %>%
dplyr::na_if("*")
table11.1a <- table11.1a %>%
tibble::as_tibble() %>%
dplyr::rename(MHS_setting = `Setting Where Mental Health ServiceWas Received`)
partA <- table11.1a %>%
dplyr::select(MHS_setting)
partB <- table11.1a %>%
select(-MHS_setting)
partA <- partA %>%
dplyr::mutate(MHS_setting = base::gsub("[[:digit:]]+|[\r\n]|[[:punct:]]|([[:blank:]])\\1+",
"",
MHS_setting))
partB <- partB %>%
mutate(dplyr::across(.cols = dplyr::everything(),
stringr::str_remove_all, "a")) %>%
mutate(dplyr::across(.cols = dplyr::everything(),
stringr::str_remove_all, ","))
base::rm(table11.1a)
table11.1a <- dplyr::bind_cols(partA,
partB)
table11.1a <- table11.1a %>%
tidyr::pivot_longer(cols = dplyr::contains("20"), names_to = "Year", values_to = "Number")
table11.1a <- table11.1a %>%
dplyr::filter(MHS_setting != "General Medicine") %>%
dplyr::filter(MHS_setting != "Juvenile Justice") #Leading lines with no data
table11.1a <- table11.1a %>%
mutate(across(c(Year, Number), as.numeric))
We will write a function to simplify this process.
The function needs to:
- remove the last row of the table
- get rid of certain patterns
- transition the data to long format
data_prep_settings <- function(TABLE, old_col, new_col, pivot_col){
TABLE <- TABLE[-dim(TABLE)[1],]
TABLE <- TABLE %>%
na_if("nc") %>%
na_if("--") %>%
na_if("") %>%
na_if("*")
TABLE <- TABLE %>%
as_tibble() %>%
rename({{new_col}} := {{old_col}})
partA <- TABLE %>%
select({{new_col}})
partB <- TABLE %>%
select(-{{new_col}})
partA <- partA %>%
mutate({{new_col}} := partA %>%
select({{new_col}}) %>%
dplyr::pull({{new_col}}) %>%
gsub("[[:digit:]]+|[\r\n]|[[:punct:]]|([[:blank:]])\\1+",
"", .))
partB <- partB %>%
mutate(across(.cols = everything(),
str_remove_all, "a")) %>%
mutate(across(.cols = everything(),
str_remove_all, ","))
rm(TABLE)
TABLE <- bind_cols(partA,
partB)
TABLE <- TABLE %>%
pivot_longer(cols = contains("20"), names_to = "Year", values_to = pivot_col)
TABLE
}
I included the following line to help separate the tables.
Table11.1a
We then apply this function to the table, ridding the table of headings and ensuring some of our commons are correctly of numeric class.
[1] 21 18
We write a function to simplify this process for data that uses demographic groups as units of observation.
The function needs to:
- remove the last row of the table
- get rid of certain patterns
- transition the data to long format
data_prep_dem <- function(TABLE, old_col, new_col, pivot_col){
TABLE <- TABLE[-dim(TABLE)[1],]
TABLE <- TABLE %>%
na_if("nc") %>%
na_if("--") %>%
na_if("") %>%
na_if("*")
TABLE <- TABLE %>%
as_tibble() %>%
rename({{new_col}} := {{old_col}})
partA <- TABLE %>%
dplyr::select({{new_col}})
partB <- TABLE %>%
dplyr::select(-{{new_col}})
partA <- partA %>%
mutate({{new_col}} := partA %>%
dplyr::select({{new_col}}) %>%
pull({{new_col}}) %>%
gsub("[\r\n]|[[:punct:]]|([[:blank:]])\\1+",
"", .))
partA <- partA %>%
mutate({{new_col}} := dplyr::case_when(stringr::str_detect(!!base::as.name(new_col), pattern = "1") ~ base::paste("Age",
stringr::str_sub(!!base::as.name(new_col),
start = 1,
end =2),
stringr::str_sub(!!base::as.name(new_col),
start = 3,
end = 4),
sep="_"),
TRUE ~ !!base::as.name(new_col)))
partB <- partB %>%
mutate(across(.cols = everything(),
str_remove_all, "a")) %>%
mutate(across(.cols = everything(),
str_remove_all, ","))
rm(TABLE)
TABLE <- bind_cols(partA,
partB)
TABLE <- TABLE %>%
pivot_longer(cols = contains("20"), names_to = "Year", values_to = pivot_col)
TABLE
}
I included the following line to help separate the tables.
Table11.2a
We use the produced function to wrangle the next pair of tables.
[1] 18 16
# A tibble: 5 x 2
Demographic n
<chr> <int>
1 AGE GROUP 15
2 AIAN 1
3 GENDER 15
4 HISPANIC ORIGIN AND RACE 15
5 NHOPI 14
I included the following line to help separate the tables.
Table11.2b
[1] 18 16
# A tibble: 5 x 2
Demographic n
<chr> <int>
1 AGE GROUP 15
2 AIAN 1
3 GENDER 15
4 HISPANIC ORIGIN AND RACE 15
5 NHOPI 14
We repeat this process for the remaining tables.
I included the following line to help separate the tables.
Table 11.3a
[1] 18 14
# A tibble: 5 x 2
Demographic n
<chr> <int>
1 AGE GROUP 13
2 AIAN 2
3 GENDER 13
4 HISPANIC ORIGIN AND RACE 13
5 NHOPI 13
I included the following line to help separate the tables.
Table 11.3b
[1] 18 14
# A tibble: 5 x 2
Demographic n
<chr> <int>
1 AGE GROUP 13
2 AIAN 2
3 GENDER 13
4 HISPANIC ORIGIN AND RACE 13
5 NHOPI 13
I included the following line to help separate the tables.
Table 11.4a
[1] 18 16
# A tibble: 7 x 2
Demographic n
<chr> <int>
1 AGE GROUP 15
2 AIAN 15
3 Asian 15
4 GENDER 15
5 HISPANIC ORIGIN AND RACE 15
6 NHOPI 15
7 Two or More Races 12
I included the following line to help separate the tables.
Table 11.4b
[1] 18 16
# A tibble: 7 x 2
Demographic n
<chr> <int>
1 AGE GROUP 15
2 AIAN 15
3 Asian 15
4 GENDER 15
5 HISPANIC ORIGIN AND RACE 15
6 NHOPI 15
7 Two or More Races 12
Now that we’ve wrangled the data, we can go ahead and proceed with our analysis.
Data Analysis
In this section, we only analyzed data from tables 2-4. Data from table 1 is very different than data from tables 2-4. For expediency, I did not include an example with data frome table 1. The following code, however, can easily be repurposed to accomplish that once a specific group has been identified to conduct the test on.
We would like to conduct a chi-squared test for independence.
To conduct this statistical test, we need to produce a 2x2 table.
The following code subsets the data we need and makes the necessary manipulations so that the units of observation are appropriate.
The resulting object is still in long format.
# A tibble: 4 x 3
Demographic Year Number
<chr> <dbl> <dbl>
1 Male 2009 577000
2 Male 2018 946000
3 Female 2009 1377000
4 Female 2018 2537000
To conduct a chi-squared test for indepence we will need a contingency table.
A contingency table can be produced from data in long format by transforming the data to wide format and repurposing some values as row names.
The final object should look like this.
Year2009 Year2018
Male 577000 946000
Female 1377000 2537000
The chi-squared test for independence can be conducted using the stats::chisq.test() function.
Pearson's Chi-squared test with Yates' continuity correction
data: chi_square_11.2a
X-squared = 3482.7, df = 1, p-value < 2.2e-16
We can repeat this process for the remaining tables.
Year2009 Year2018
Male 391000 628000
Female 1013000 1795000
Pearson's Chi-squared test with Yates' continuity correction
data: chi_square_11.3a
X-squared = 1696, df = 1, p-value < 2.2e-16
Year2009 Year2018
Male 168000 351000
Female 505000 1081000
Pearson's Chi-squared test with Yates' continuity correction
data: chi_square_11.4a
X-squared = 50.256, df = 1, p-value = 1.349e-12
Data Visualization
This is the intentionally terrible plot that requires faceting.
table11.1b %>%
ggplot2::ggplot(aes(x = Year, y = Percent, group = MHS_setting)) +
ggplot2::geom_line() +
ggplot2::scale_x_continuous(breaks = seq(2009, 2018, by=1),
labels = seq(2009, 2018, by=1),
limits = c(2009, 2018)) +
ggplot2::labs(title = "Settings Where Mental Health Services Were Received in Past Year\namong Persons Aged 12 to 17",
subtitle = "Percentages, 2002-2018")

The plots below need to be correctly faceted. Keep in mind that tables 11.2+ must be faceted by demographic group type and not by setting type.
table11.1b %>%
ggplot(aes(x = Year, y = Percent, group = MHS_setting)) +
geom_line() +
scale_x_continuous(breaks = seq(2009, 2018, by=1),
labels = seq(2009, 2018, by=1),
limits = c(2009, 2018)) +
labs(title = "Settings Where Mental Health Services Were Received in Past Year\namong Persons Aged 12 to 17",
subtitle = "Percentages, 2002-2018")

table11.2b %>%
ggplot(aes(x = Year, y = Percent, group = Demographic)) +
geom_line() +
scale_x_continuous(breaks = seq(2009, 2018, by=1),
labels = seq(2009, 2018, by=1),
limits = c(2009, 2018)) +
labs(title = "Major Depressive Episode in Past Year\namong Persons Aged 12 to 17",
subtitle = "By Demographic Characteristics, Percentages, 2004-2018")

table11.3b %>%
ggplot(aes(x = Year, y = Percent, group = Demographic)) +
geom_line() +
scale_x_continuous(breaks = seq(2009, 2018, by=1),
labels = seq(2009, 2018, by=1),
limits = c(2009, 2018)) +
labs(title = "Major Depressive Episode with Severe Impairment in Past Year\namong Persons Aged 12 to 17",
subtitle = "By Demographic Characteristics: Percentages, 2006-2018")

table11.4b %>%
ggplot(aes(x = Year, y = Percent, group = Demographic)) +
geom_line() +
scale_x_continuous(breaks = seq(2009, 2018, by=1),
labels = seq(2009, 2018, by=1),
limits = c(2009, 2018)) +
labs(title = "Receipt of Treatment for Depression in Past Year among\nPersons Aged 12 to 17 with Major Depressive Episode in Past Year",
subtitle = "By Demographic Characteristics: Percentages, 2004-2018")

The plots created (after faceting properly) can be used to answer the questions listed at the beginning of the case study. After finalizing the plots, some time should be spent towards framing the visualizations in such a way to underscore how they were used to asnwer the question.
Summary
Suggested Homework
LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXMgOiBNZW50YWwgSGVhbHRoIG9mIEFtZXJpY2FuIFlvdXRoIgpjc3M6IHN0eWxlLmNzcwpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHNlbGZfY29udGFpbmVkOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgbnVtYmVyX3NlY3Rpb25zOiBubwogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwoKLS0tCjxzdHlsZT4KI1RPQyB7CiAgYmFja2dyb3VuZDogdXJsKCJodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8vaW1nL2xvZ28uanBnIik7CiAgYmFja2dyb3VuZC1zaXplOiBjb250YWluOwogIHBhZGRpbmctdG9wOiAyNDBweCAhaW1wb3J0YW50OwogIGJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7Cn0KPC9zdHlsZT4KCgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChpbmNsdWRlID0gVFJVRSwgY29tbWVudCA9IE5BLCBlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBjYWNoZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLmFsaWduID0gImNlbnRlciIsIG91dC53aWR0aCA9ICc5MCUnKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkobWFnaWNrKQpgYGAKCiMjIHsuZGlzY2xhaW1lcl9ibG9ja30KCioqRGlzY2xhaW1lcioqOiBUaGUgcHVycG9zZSBvZiB0aGUgW09wZW4gQ2FzZSBTdHVkaWVzXShodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8pe3RhcmdldD0iX2JsYW5rIn0gcHJvamVjdCBpcyAqKnRvIGRlbW9uc3RyYXRlIHRoZSB1c2Ugb2YgdmFyaW91cyBkYXRhIHNjaWVuY2UgbWV0aG9kcywgdG9vbHMsIGFuZCBzb2Z0d2FyZSBpbiB0aGUgY29udGV4dCBvZiBtZXNzeSwgcmVhbC13b3JsZCBkYXRhKiouIEEgZ2l2ZW4gY2FzZSBzdHVkeSBkb2VzIG5vdCBjb3ZlciBhbGwgYXNwZWN0cyBvZiB0aGUgcmVzZWFyY2ggcHJvY2VzcywgaXMgbm90IGNsYWltaW5nIHRvIGJlIHRoZSBtb3N0IGFwcHJvcHJpYXRlIHdheSB0byBhbmFseXplIGEgZ2l2ZW4gZGF0YSBzZXQsIGFuZCBzaG91bGQgbm90IGJlIHVzZWQgaW4gdGhlIGNvbnRleHQgb2YgbWFraW5nIHBvbGljeSBkZWNpc2lvbnMgd2l0aG91dCBleHRlcm5hbCBjb25zdWx0YXRpb24gZnJvbSBzY2llbnRpZmljIGV4cGVydHMuIAoKIyMgey5saWNlbnNlX2Jsb2NrfQoKVGhpcyB3b3JrIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBDcmVhdGl2ZSBDb21tb25zIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFsoQ0MgQlktTkMgMy4wKV0oaHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC91cy8pe3RhcmdldD0iX2JsYW5rIn0gIFVuaXRlZCBTdGF0ZXMgTGljZW5zZS4KCiMjIHsucmVmZXJlbmNlX2Jsb2NrfQoKVG8gY2l0ZSB0aGlzIGNhc2Ugc3R1ZHkgcGxlYXNlIHVzZToKCldyaWdodCwgQ2FycmllLCBhbmQgT250aXZlcm9zLCBNaWNoYWVsIGFuZCBKYWdlciwgTGVhaCBhbmQgVGF1YiwgTWFyZ2FyZXQgYW5kIEhpY2tzLCBTdGVwaGFuaWUuICgyMDIwKS4gaHR0cHM6Ly9naXRodWIuY29tL29wZW5jYXNlc3R1ZGllcy9vY3MtYnAtY28yLWVtaXNzaW9ucy4gTWVudGFsIEhlYWx0aCBvZiBBbWVyaWNhbiBZb3V0aCAoVmVyc2lvbiB2MS4wLjApLgoKCiMjICoqTW90aXZhdGlvbioqCioqKiAKClRoZSBmb2xsb3dpbmcgcGFwZXJzIG1vdGl2YXRlZCB0aGlzIGNhc2Ugc3R1ZHkuIAoKIyMjIyB7LnJlZmVyZW5jZV9ibG9ja30KClR3ZW5nZSBKTSwgQ29vcGVyIEFCLCBKb2luZXIgVEUsIER1ZmZ5IE1FLCBCaW5hdSBTRy4gQWdlLCBwZXJpb2QsIGFuZCBjb2hvcnQgdHJlbmRzIGluIG1vb2QgZGlzb3JkZXIgaW5kaWNhdG9ycyBhbmQgc3VpY2lkZS1yZWxhdGVkIG91dGNvbWVzIGluIGEgbmF0aW9uYWxseSByZXByZXNlbnRhdGl2ZSBkYXRhc2V0LCAyMDA1LTIwMTcuICpKIEFibm9ybSBQc3ljaG9sKi4xMjgsMyAoMjAxOSk6MTg1LTE5OS4gZG9pOjEwLjEwMzcvYWJuMDAwMDQxMAoKCk9sZnNvbiwgTS4sIEJsYW5jbywgQy4sIFdhbmcsIFMuLCBMYWplLCBHLiAmIENvcnJlbGwsIEMuIFUuIE5hdGlvbmFsIFRyZW5kcyBpbiB0aGUgTWVudGFsIEhlYWx0aCBDYXJlIG9mIENoaWxkcmVuLCBBZG9sZXNjZW50cywgYW5kIEFkdWx0cyBieSBPZmZpY2UtQmFzZWQgUGh5c2ljaWFucy4gKkpBTUEgUHN5Y2hpYXRyeSouIDcxLCA4MSAoMjAxNCk6ODEtOTAuIGRvaTogMTAuMTAwMS9qYW1hcHN5Y2hpYXRyeS4yMDEzLjMwNzQuCgojIyMjCgpUaGUgbWFpbiBmaW5kaW5ncyBvZiB0aGUgZmlyc3QgW2FydGljbGVdKGh0dHBzOi8vY29udGVudC5hcGEub3JnL3JlY29yZC8yMDE5LTEyNTc4LTAwMSl7dGFyZ2V0PSJfYmxhbmsifSBhcmU6Cgo+UmF0ZXMgb2YgbWFqb3IgZGVwcmVzc2l2ZSBlcGlzb2RlIGluIHRoZSBsYXN0IHllYXIgaW5jcmVhc2VkIDUyJSAyMDA14oCTMjAxNyAoZnJvbSA4LjclIHRvIDEzLjIlKSBhbW9uZyBhZG9sZXNjZW50cyBhZ2VkIDEyIHRvIDE3IGFuZCA2MyUgMjAwOeKAkzIwMTcgKGZyb20gOC4xJSB0byAxMy4yJSkgYW1vbmcgeW91bmcgYWR1bHRzIDE44oCTMjUuIAoKPlNlcmlvdXMgcHN5Y2hvbG9naWNhbCBkaXN0cmVzcyBpbiB0aGUgbGFzdCBtb250aCBhbmQgc3VpY2lkZS1yZWxhdGVkIG91dGNvbWVzIChzdWljaWRhbCBpZGVhdGlvbiwgcGxhbnMsIGF0dGVtcHRzLCBhbmQgZGVhdGhzIGJ5IHN1aWNpZGUpIGluIHRoZSBsYXN0IHllYXIgYWxzbyBpbmNyZWFzZWQgYW1vbmcgeW91bmcgYWR1bHRzIDE44oCTMjUgZnJvbSAyMDA44oCTMjAxNyAod2l0aCBhIDcxJSBpbmNyZWFzZSBpbiBzZXJpb3VzIHBzeWNob2xvZ2ljYWwgZGlzdHJlc3MpLCB3aXRoIGxlc3MgY29uc2lzdGVudCBhbmQgd2Vha2VyIGluY3JlYXNlcyBhbW9uZyBhZHVsdHMgYWdlcyAyNiBhbmQgb3Zlci4gCgo+Q3VsdHVyYWwgdHJlbmRzIGNvbnRyaWJ1dGluZyB0byBhbiBpbmNyZWFzZSBpbiBtb29kIGRpc29yZGVycyBhbmQgc3VpY2lkYWwgdGhvdWdodHMgYW5kIGJlaGF2aW9ycyBzaW5jZSB0aGUgbWlkLTIwMDBzLCBpbmNsdWRpbmcgdGhlIHJpc2Ugb2YgZWxlY3Ryb25pYyBjb21tdW5pY2F0aW9uIGFuZCBkaWdpdGFsIG1lZGlhIGFuZCBkZWNsaW5lcyBpbiBzbGVlcCBkdXJhdGlvbiwgbWF5IGhhdmUgaGFkIGEgbGFyZ2VyIGltcGFjdCBvbiB5b3VuZ2VyIHBlb3BsZSwgY3JlYXRpbmcgYSBjb2hvcnQgZWZmZWN0LgoKV2hpbGUgdGhlIG1haW4gZmluZGluZ3Mgb2YgdGhlIHNlY29uZCBbYXJ0aWNsZV0oaHR0cHM6Ly9wdWJtZWQubmNiaS5ubG0ubmloLmdvdi8yNDI4NTM4Mi8pe3RhcmdldD0iX2JsYW5rIn0gYXJlOgoKPkNvbXBhcmVkIHdpdGggYWR1bHQgbWVudGFsIGhlYWx0aCBjYXJlLCB0aGUgbWVudGFsIGhlYWx0aApjYXJlIG9mIHlvdW5nIHBlb3BsZSBoYXMgaW5jcmVhc2VkIG1vcmUgcmFwaWRseS4KCj5CZXR3ZWVuIDE5OTUtMTk5OCBhbmQgMjAwNy0yMDEwLCB2aXNpdHMgcmVzdWx0aW5nIGluIG1lbnRhbCBkaXNvcmRlciBkaWFnbm9zZXMKcGVyIDEwMCBwb3B1bGF0aW9uIGluY3JlYXNlZCBzaWduaWZpY2FudGx5IGZhc3RlciBmb3IgeW91dGhzIChmcm9tIDcuNzggdG8gMTUuMzAgdmlzaXRzKSB0aGFuIGZvcgphZHVsdHMgKGZyb20gMjMuMjMgdG8gMjguNDggdmlzaXRzKSAoaW50ZXJhY3Rpb246IFAgPCAuMDAxKS4gCgo+UHN5Y2hpYXRyaXN0IHZpc2l0cyBhbHNvIGluY3JlYXNlZApzaWduaWZpY2FudGx5IGZhc3RlciBmb3IgeW91dGhzIChmcm9tIDIuODYgdG8gNS43MSB2aXNpdHMpLgoKCldoaWxlIGRlcHJlc3Npb24gYXBwZWFyIHRvIGJlIG9uIHRoZSByaXNlIGZvciB5b3V0aHMsIHlvdXRocyBhbHNvIGFwcGVhciB0byBiZSBzZWVraW5nIG1vcmUgbWVudGFsIGhlYWx0aCBjYXJlLgoKSW4gdGhpcyBjYXNlIHN0dWR5IHdlIHdpbGwgZXZhbHVhdGUgZGF0YSByZWxhdGVkIHRvIGRlcHJlc3Npb24gZXBpc29kZXMgYW5kIG1lbnRhbCBoZWFsdGggY2FyZSB0byBldmFsdWF0ZSB0cmVuZHMgb3ZlcnRpbWUuIFdlIHdpbGwgYmUgdXNpbmcgZGF0YSBmcm9tIHRoZSBbTmF0aW9uYWwgU3VydmV5IG9uIERydWcgVXNlIGFuZCBIZWFsdGggKE5TRFVIKV0oaHR0cHM6Ly9uc2R1aHdlYi5ydGkub3JnL3Jlc3B3ZWIvaG9tZXBhZ2UuY2ZtKS4gVGhpcyBkYXRhIHdhcyBhbHNvIHVzZWQgaW4gdGhlIGZpcnN0IHN0dWR5LiAgCgoKIyMgKipNYWluIFF1ZXN0aW9ucyoqCioqKiAKCiMjIyMgey5tYWluX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gT3VyIG1haW4gcXVlc3Rpb25zOiA8L3U+PC9iPgoKMSkgSG93IGhhdmUgZGVwcmVzc2lvbiByYXRlcyBpbiBBbWVyaWNhbiB5b3V0aCBjaGFuZ2VkIHNpbmNlIDIwMDIsIGFjY29yZGluZyB0byB0aGUgTlNEVUggZGF0YT8gIAoyKSBEbyBtZW50YWwgaGVhbHRoIHNlcnZpY2VzIGFwcGVhciB0byBiZSByZWFjaGluZyBtb3JlIHlvdXRocz8gSG93IGhhdmUgcmF0ZXMgZGlmZmVyZWQgYmV0d2VlbiBkaWZmZXJlbnQgeW91dGggc3ViZ3JvdXBzIChnZW5kZXIsIGV0aG5pY2l0eSk/CgojIyMjCgojIyAqKkxlYXJuaW5nIE9iamVjdGl2ZXMqKiAKKioqIAoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKkl0IG1heSBiZSBhIGdvb2QgaWRlYSB0byBwcm92aWRlIGEgbGluayB0byBSc3R1ZGlvJ3Mgd2VicGFnZS4gRm9yIHRoZSBmaXJzdCBmZXcgbW9udGhzIHVzaW5nIFIsIEkgZGlkIG5vdCBkaWZmZXJlbnRpYXRlIGJldHdlZW4gUiBhbmQgUiBTdHVkaW8uIEl0IG1heSBiZSBhIGdvb2QgZGlzdGluY3Rpb24gdG8gbWFrZSBhdCBsZWFzdCBpbXBsaWNpdGx5IGJ5IHByb3ZpZGluZyBhIGxpbmsuKioKCjwvZGl2PgoKSW4gdGhpcyBjYXNlIHN0dWR5LCB3ZSB3aWxsIGRldGVybWluZSB0aGUgcGVyY2VudCBvZiB5b3V0aCBpbiBBbWVyaWNhIHRoYXQgaGF2ZSBoYWQgYSBtYWpvciBkZXByZXNzaXZlIGVwaXNvZGUgaW4gdGhlIHBhc3QgeWVhciBzaW5jZSAyMDAyLiBXZSB3aWxsIGNvbXBhcmUgaG93IGRpZmZlcmVudCB5b3V0aCBzdWJncm91cHMgaGF2ZSBjaGFuZ2VkIG92ZXIgdGltZSAoYnkgYWdlIGdyb3VwICgxMi0xMywxNC0xNSwgYW5kIDE2LTE3KSwgZ2VuZGVyLCBldGhuaWNpdHkpLgpXZSB3aWxsIGVzcGVjaWFsbHkgZm9jdXMgb24gdXNpbmcgcGFja2FnZXMgYW5kIGZ1bmN0aW9ucyBmcm9tIHRoZSBbYFRpZHl2ZXJzZWBdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9LCBzdWNoIGFzIFtgcnZlc3RgXShodHRwczovL2dpdGh1Yi5jb20vdGlkeXZlcnNlL3J2ZXN0KS4gVGhlIHRpZHl2ZXJzZSBpcyBhIGxpYnJhcnkgb2YgcGFja2FnZXMgY3JlYXRlZCBieSBSU3R1ZGlvLiBXaGlsZSBzb21lIHN0dWRlbnRzIG1heSBiZSBmYW1pbGlhciB3aXRoIHByZXZpb3VzIFIgcHJvZ3JhbW1pbmcgcGFja2FnZXMsIHRoZXNlIHBhY2thZ2VzIG1ha2UgZGF0YSBzY2llbmNlIGluIFIgZXNwZWNpYWxseSBlZmZpY2llbnQuCgpgYGB7ciwgb3V0LndpZHRoID0gIjIwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly90aWR5dmVyc2UudGlkeXZlcnNlLm9yZy9sb2dvLnBuZyIpCmBgYAoKKioqIAoKV2Ugd2lsbCBiZWdpbiBieSBsb2FkaW5nIHRoZSBwYWNrYWdlcyB0aGF0IHdlIHdpbGwgbmVlZDoKCmBgYHtyfQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHJ2ZXN0KQpgYGAKCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipJIG1hZGUgc29tZSBtb2RpZmljYXRpb25zIHRvIHRoZSB0YWJsZSBiZWxvdy4gVGhlIGB0aWR5dmVyc2VgIHBhY2thZ2UgaHlwZXJsaW5rIHJlZmVyZW5jZWQgYHJlYWRyYC4gSSB0aG91Z2h0IHRoaXMgd2FzIGluY29ycmVjdC4gSSBjaGFuZ2VkIHRoaXMgdG8gdGhlIHRpZHl2ZXJzZSB3ZWJzaXRlIGFuZCBwcm92aWRlZCBhIGRpZmZlcmVudCBkZXNjcmlwdGlvbi4gSWYgdGhpcyB3YXMgaW5kZWVkIGEgdHlwbywgaXQgbWF5IG5lZWQgdG8gYmUgZml4ZWQgaW4gb3RoZXIgY2FzZSBzdHVkaWVzLioqCgo8L2Rpdj4KCiBQYWNrYWdlICAgfCBVc2UgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCi0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS0KW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9qZW5ueWJjL2hlcmVfaGVyZSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgICB8IHRvIGVhc2lseSBsb2FkIGFuZCBzYXZlIGRhdGEKW3RpZHl2ZXJzZV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IFIgcGFja2FnZXMgZm9yIGRhdGEgc2NpZW5jZQpbcnZlc3RdKGh0dHBzOi8vZ2l0aHViLmNvbS90aWR5dmVyc2UvcnZlc3Qpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIHNjcmFwZSB3ZWIgcGFnZXMKClRoZSBmaXJzdCB0aW1lIHdlIHVzZSBhIGZ1bmN0aW9uLCB3ZSB3aWxsIHVzZSB0aGUgYDo6YCB0byBpbmRpY2F0ZSB3aGljaCBwYWNrYWdlIHdlIGFyZSB1c2luZy4gVW5sZXNzIHdlIGhhdmUgb3ZlcmxhcHBpbmcgZnVuY3Rpb24gbmFtZXMsIHRoaXMgaXMgbm90IG5lY2Vzc2FyeSwgYnV0IHdlIHdpbGwgaW5jbHVkZSBpdCBoZXJlIHRvIGJlIGluZm9ybWF0aXZlIGFib3V0IHdoZXJlIHRoZSBmdW5jdGlvbnMgd2Ugd2lsbCB1c2UgY29tZSBmcm9tLgoKIyMgKipDb250ZXh0KioKKioqIAoKQWNjb3JkaW5nIHRvIG90aGVyIHNvdXJjZXMgdGhlIHJhdGUgb2Ygc3VpY2lkZSBoYXMgaW5jcmVhc2VkIGZvciBtb3N0IGFnZSBncm91cHMgaW4gdGhlIFVuaXRlZCBTdGF0ZXMgb3ZlciB0aGUgcGFzdCBkZWNhZGUgYW5kIGEgaGFsZi4KCmBgYHtyLCBvdXQud2lkdGggPSAiODAlIiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL3d3dy5jZGMuZ292L25jaHMvaW1hZ2VzL2RhdGFicmllZnMvMzAxLTM1MC9kYjMwOV9maWcxLnBuZyIpCmBgYAoKIyMjIyBbW3NvdXJjZV0oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL3Byb2R1Y3RzL2RhdGFicmllZnMvZGIzMDkuaHRtKV17dGFyZ2V0PSJfYmxhbmsifQoKCldoaWxlIHN1aWNpZGUgZG9lcyBhcHBlYXIgdG8gYmUgaW5jcmVhc2luZyBhbW91bmcgeW91dGhzIGl0IGFsc28gYXBwZWFycyB0byBiZSBpbmNyZWFzaW5nIGFtb3VuZyBtaWRkbGUgYWdlZCBhZHVsdHMgYXMgd2VsbCBmb3IgYm90aCBmZW1hbGVzIGFuZCBtYWxlcy4gCgpgYGB7ciwgb3V0LndpZHRoID0gIjgwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2ltYWdlcy9kYXRhYnJpZWZzLzMwMS0zNTAvZGIzMDlfZmlnMi5wbmciKQpgYGAKCiMjIyMgW1tzb3VyY2VdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9wcm9kdWN0cy9kYXRhYnJpZWZzL2RiMzA5Lmh0bSlde3RhcmdldD0iX2JsYW5rIn0KCgoKCmBgYHtyLCBvdXQud2lkdGggPSAiODAlIiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL3d3dy5jZGMuZ292L25jaHMvaW1hZ2VzL2RhdGFicmllZnMvMzAxLTM1MC9kYjMwOV9maWczLnBuZyIpCmBgYAoKIyMjIyBbW3NvdXJjZV0oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL3Byb2R1Y3RzL2RhdGFicmllZnMvZGIzMDkuaHRtKV17dGFyZ2V0PSJfYmxhbmsifQoKCkFjY29yZGluZyB0byB0aGUgW0NEQ10oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL3Byb2R1Y3RzL2RhdGFicmllZnMvZGIzMDkuaHRtKXt0YXJnZXQ9Il9ibGFuayJ9OgoKPiBTaW5jZSAyMDA4LCBzdWljaWRlIGhhcyByYW5rZWQgYXMgdGhlIDEwdGggbGVhZGluZyBjYXVzZSBvZiBkZWF0aCBmb3IgYWxsIGFnZXMgaW4gdGhlIFVuaXRlZCBTdGF0ZXMuIEluIDIwMTYsIHN1aWNpZGUgYmVjYW1lIHRoZSAqKnNlY29uZCBsZWFkaW5nIGNhdXNlIG9mIGRlYXRoKiogYW1vbmcgdGhvc2UgYWdlZCAqKjEw4oCTMzQqKiBhbmQgdGhlIGZvdXJ0aCBsZWFkaW5nIGNhdXNlIGFtb25nIHRob3NlIGFnZWQgMzXigJM1NC4KCgoqKlNvIGFsdGhvdWdoIHN1Y2lkZSBpcyBvbiB0aGUgcmlzZSBmb3IgbW9zdCBhZ2UgZ3JvdXBzLCBzdWNpZGUgaXMgb25lIG9mIHRoZSB0b3AgdHdvIGNvbnRyaWJ1dG9ycyB0byBkZWF0aCBmb3IgeW91dGhzLioqIFRoaXMgd2FycmVudHMgZnVydGhlciBleGFtaW5hdGlvbiBvZiBtZW50YWwgaGVhbHRoIG9mIEFtZXJpY2FuIHlvdXRocy4KCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJtb3J0YWxpdHkucG5nIikpCmBgYAoKIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9kYXRhL2RhdGFicmllZnMvZGIyOTMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9CgoKYWNjb3JkaW5nIHRvIHRoaXMgYXJ0aWNsZTpodHRwczovL3d3dy51c2F0b2RheS5jb20vc3RvcnkvbmV3cy9uYXRpb24vMjAyMC8wMS8zMC91LXMtc3VpY2lkZS1yYXRlLXJvc2UtYWdhaW4tMjAxOC1ob3ctY2FuLXN1aWNpZGUtcHJldmVudGlvbi1zYXZlLWxpdmVzLzQ2MTY0NzkwMDIvCj5EZWF0aCByYXRlcyBpbiAyMDE4IGluY3JlYXNlZCBmb3Igb25seSB0d28gb2YgdGhlIDEwIGxlYWRpbmcgY2F1c2VzIG9mIGRlYXRoOiBzdWljaWRlIGFuZCBpbmZsdWVuemEvcG5ldW1vbmlhLiBJRGsgaWYgdGhpcyBpcyB0cnVlLi4uCgoqSWYgeW91IGFyZSBoYXZpbmcgdGhvdWdodHMgb2Ygc3VpY2lkZSwgcGxlYXNlIGtub3cgdGhhdCB5b3UgYXJlIG5vdCBhbG9uZS4gSWYgeW91IGFyZSBpbiBkYW5nZXIgb2YgYWN0aW5nIG9uIHN1aWNpZGFsIHRob3VnaHRzLCBjYWxsIDkxMS4gRm9yIHN1cHBvcnQgYW5kIHJlc291cmNlcywgY2FsbCB0aGUgTmF0aW9uYWwgU3VpY2lkZSBQcmV2ZW50aW9uIExpZmVsaW5lIGF0IDEtODAwLTI3My04MjU1IG9yIHRleHQgNzQxLTc0MSBmb3IgdGhlIENyaXNpcyBUZXh0IExpbmUuKgoKSSB0b29rIHRoaXMgZnJvbSBhbiBhcnRpY2xlLmh0dHBzOi8vd3d3LnRoZWF0bGFudGljLmNvbS9oZWFsdGgvYXJjaGl2ZS8yMDIwLzA2L3doeS1zdWljaWRlLXJhdGVzLWFtb25nLW1pbGxlbm5pYWxzLWFyZS1yaXNpbmcvNjEyOTQzLwoKKklmIHlvdSBvciBzb21lb25lIHlvdSBrbm93IG1heSBiZSBzdHJ1Z2dsaW5nIHdpdGggc3VpY2lkYWwgdGhvdWdodHMsIHlvdSBjYW4gY2FsbCB0aGUgVS5TLiBOYXRpb25hbCBTdWljaWRlIFByZXZlbnRpb24gTGlmZWxpbmUgYXQgODAwLTI3My1UQUxLICg4MjU1KSBhbnkgdGltZSBkYXkgb3IgbmlnaHQsIG9yIGNoYXQgb25saW5lLioKSSB0aG9vayB0aG9zIGZyb20gdGhpcyBhcnRpY2xlLiBodHRwczovL3d3dy51c2F0b2RheS5jb20vc3RvcnkvbmV3cy9uYXRpb24vMjAyMC8wMS8zMC91LXMtc3VpY2lkZS1yYXRlLXJvc2UtYWdhaW4tMjAxOC1ob3ctY2FuLXN1aWNpZGUtcHJldmVudGlvbi1zYXZlLWxpdmVzLzQ2MTY0NzkwMDIvCgoKCgpjb3ZpZDpodHRwczovL3dlbGxiZWluZ3RydXN0Lm9yZy9hcmVhcy1vZi1mb2N1cy9wb2xpY3ktYW5kLWFkdm9jYWN5L3JlcG9ydHMvcHJvamVjdGVkLWRlYXRocy1vZi1kZXNwYWlyLWR1cmluZy1jb3ZpZC0xOS8KCkhpc3RvcmljYWxseSwgc3VpY2lkZSByYXRlcyB3ZXJlIG11Y2ggaGlnaGVyIGJlZm9yZSAxOTUwLCBob3dldmVyLCB3ZSBhcmUgc2VlaW5nIGFuIGluY3JlYXNlIGluIHRoZSBsYXN0IDIwIHllYXJzLgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInN1aWNpZGUucG5nIikpCmBgYAoKIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vdGltZS5jb20vNTYwOTEyNC91cy1zdWljaWRlLXJhdGUtaW5jcmVhc2UvKXt0YXJnZXQ9Il9ibGFuayJ9CgoKCgoKQmVzaWRlcyB0aGUgVVMsIFtvdGhlciBjb3VudHJpZXNdKGh0dHBzOi8vYWNhZGVtaWMub3VwLmNvbS9pamUvYXJ0aWNsZS80OC81LzE2NTAvNTM2NjIxMCl7dGFyZ2V0PSJfYmxhbmsifSBhcmUgYWxzbyBleHBlcmllbmNpbmcgaW5jcmVhc2VkIHJlYXRlcyBvZiBkZXByZXNzaW9uIGluIHlvdXRocy4gU2VlIFt0aGlzIHJlcG9ydF0oaHR0cHM6Ly9hcHBzLndoby5pbnQvaXJpcy9iaXRzdHJlYW0vaGFuZGxlLzEwNjY1LzI1NDYxMC9XSE8tTVNELU1FUi0yMDE3LjItZW5nLnBkZjtqc2Vzc2lvbmlkPUU0NDM2MDA1NUREODNFQUM0NzJBQTQwQzI4NTNEQkZBP3NlcXVlbmNlPTEpe3RhcmdldD0iX2JsYW5rIn0gZnJvbSB0aGUgIFdvcmxkIEhlYWx0aCBPcmdhbml6YXRpb24gYWJvdXQgcmF0ZXMgb2YgZGVwcmVzc2lvbiBpbiBvdGhlciBjb3VudHJpZXMuCgpHcmVhdCBwYXBlciBhYm91dCB3aGF0IG1heSBiZSBjYXVzaW5nIGluY3JlYXNlZCBkcHJlc3Npb24gLSBhbmQgdGhlIGNhdmVhdHMgb2YgaWYgd2UgYWN0dWFsbHkgaGF2ZSBpbmNyZWFzZWQgZGVwcmVzc2lvbjogaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DMzMzMDE2MS8KCgoKaGVscDpodHRwczovL3d3dy5taGFuYXRpb25hbC5vcmcvZGVwcmVzc2lvbi10ZWVucy0wCgpodHRwczovL3d3dy5uaW1oLm5paC5nb3YvaGVhbHRoL3B1YmxpY2F0aW9ucy90ZWVuLWRlcHJlc3Npb24vaW5kZXguc2h0bWwKCiMjICoqTGltaXRhdGlvbnMqKgoqKiogCgo8c3R5bGU+CmRpdi5yZWQgeyBiYWNrZ3JvdW5kLWNvbG9yOiNGRkU2RTY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAicmVkIj4KCioqUGVyaGFwcyAidW5kZXJlc3RpbWF0ZXMgaW4gdGhlIHAtdmFsdWVzLi4uIiBpcyBub3QgdGhlIGNvcnJlY3Qgd2F5IHRvIHBocmFzZSB0aGlzLiBJIHdvdWxkIGxvb2sgZm9yIGEgYmV0dGVyIHdheSB0byB3b3JkIHRoaXMuKioKCjwvZGl2PgoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKldvcmRpbmcgZm9yIHRoaXMgc2VjdGlvbiBzaG91bGQgYmUgcmV2aWV3ZWQuKioKCjwvZGl2PgoKVGhlcmUgYXJlIHNvbWUgaW1wb3J0YW50IGNvbnNpZGVyYXRpb25zIHJlZ2FyZGluZyB0aGlzIGRhdGEgYW5hbHlzaXMgdG8ga2VlcCBpbiBtaW5kOiAKCjEpIFdlIHRyZWF0IHNhbXBsZSBlc3RpbWF0ZXPigJRlc3RpbWF0ZXMgb2YgdGhlIHRydWUgcG9wdWxhdGlvbiB2YWx1ZeKAlGFzIG9ic2VydmVkIHZhbHVlcy4gVGhpcyBwcm9kdWNlcyB1bmRlcnN0aW1hdGVzIGluIHRoZSBwLXZhbHVlcyBvZiBzdGF0aXN0aWNhbCB0ZXN0cyBjb25kdWN0ZWQuCgoyKSBGdXJ0aGVybW9yZSwgdGhlIHNhbXBsaW5nIG1lY2hhbmlzbSB1dGlsaXplZCBjYW4gaW50cm9kdWNlIFtzZWxlY3Rpb24gYmlhc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU2VsZWN0aW9uX2JpYXM/b2xkZm9ybWF0PXRydWUpe3RhcmdldD0iX2JsYW5rIn0gaW4gY2FzZXMgd2hlcmUgdGhlIHRoZSBbc2FtcGxpbmcgbWV0aG9kcyBkbyBub3QgcHJvZHVjZSBhIHJlcHJlc2VudGF0aXZlIHNhbXBsZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU2FtcGxpbmdfKHN0YXRpc3RpY3MpP29sZGZvcm1hdD10cnVlKXt0YXJnZXQ9Il9ibGFuayJ9LiAKCjMpIERhdGEgaXMgY29sbGVjdGVkIGZyb20gaHVtYW4gcGFydGljaXBhbnRzOyB0aGlzIHByZXNlbnRzIHRoZSAqcG90ZW50aWFsKiBmb3IgaW5mb3JtYXRpb24gYmlhcywgYXMgdGhlcmUgaXMgdGhlICpwb3RlbnRpYWwqIHRoYXQgcGFydGlmaWNpcGFudHMgaW4gdGhlIFtzYW1wbGluZyBmcmFtZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU2FtcGxpbmdfZnJhbWU/b2xkZm9ybWF0PXRydWUpe3RhcmdldD0iX2JsYW5rIn0gbWF5IGZvciBhIHZhcmlldHkgb2YgcmVhc29ucyByZXBvcnQgaW5hY2N1cmF0ZSBpbmZvcm1hdGlvbi4gCgojIyAqKldoYXQgYXJlIHRoZSBkYXRhPyoqCioqKiAKClRoZSBkYXRhIGNvbWVzIGZyb20gdGhlIFtOYXRpb25hbCBTdXJ2ZXkgb24gRHJ1ZyBVc2UgYW5kIEhlYWx0aCAoTlNEVUgpXShodHRwczovL25zZHVod2ViLnJ0aS5vcmcvcmVzcHdlYi9ob21lcGFnZS5jZm0pe3RhcmdldD0iX2JsYW5rIn0gd2hpY2ggaXMgZGlyZWN0ZWQgYnkgdGhlIFtTdWJzdGFuY2UgQWJ1c2UgYW5kIE1lbnRhbCBIZWFsdGggU2VydmljZXMgQWRtaW5pc3RyYXRpb24gKFNBTUhTQSldKGh0dHBzOi8vd3d3LnNhbWhzYS5nb3YvKXt0YXJnZXQ9Il9ibGFuayJ9LCBhbiBhZ2VuY3kgaW4gdGhlIFtVLlMuIERlcGFydG1lbnQgb2YgSGVhbHRoIGFuZCBIdW1hbiBTZXJ2aWNlcyAoREhIUyldKGh0dHBzOi8vd3d3Lmhocy5nb3YvKXt0YXJnZXQ9Il9ibGFuayJ9LiAKClRoaXMgc3VydmV5IHN0YXJ0ZWQgaW4gMTk3MSBhbmQgaXMgY29uZHVjdGVkIGFubnVhbCBpbiBhbGwgNTAgc3RhdGVzIGFuZCB0aGUgRGlzdHJpY3Qgb2YgQ29sdW1iaWEuCgpUaGlzIGluZm9ybWF0aW9uIGlzIHVzZWQgZm9yIGRpc2Vhc2Ugc3VydmVpbGxhbmNlIGFuZCB0byBndWlkZSBwdWJsaWMgcG9saWN5LiAKClRoaXMgZGF0YSBpcyBtYWRlIGF2YWlsYWJsZSBwdWJsaWNseSBvbmxpbmUgb24gdGhlIFtTdWJzdGFuY2UgQWJ1c2UgJiBNZW50YWwgSGVhbHRoIERhdGEgQXJjaGl2ZV0oaHR0cHM6Ly9kYXRhZmlsZXMuc2FtaHNhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0uIAoKYGBge3IsIG91dC53aWR0aCA9ICIxMDAlIiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQppbmNsdWRlX2dyYXBoaWNzKGhlcmUoIm5zdWRoX3NjcmVlbnNob3Rfd2VicGFnZS5wbmciKSkKYGBgCgojIyAqKkRhdGEgSW1wb3J0KioKKioqIAoKRGF0YSBpcyBvZnRlbiBtYWRlIGF2YWlsYWJsZSBvbmxpbmUuIFVzdWFsbHksIHRoZSBkYXRhIHdlIGFyZSBpbnRlcmVzdGVkIGluIGlzIG1hZGUgYXZhaWxhYmxlIGZvciBkb3dubG9hZCBvbiB0aGUgcGFnZSBhcyBhIGRlbGltaXRlZCB0ZXh0IGZpbGUuIEhvd2V2ZXIsIHNvbWV0aW1lcyBkYXRhIGlzIG5vdCBtYWRlIGF2YWlsYWJsZSBpbiB0aGlzIG1hbm5lci4KCkhvdyBkbyB3ZSBwcm9jZWVkIGluIHRoaXMgc2NlbmFyaW8/CgpXZSBjYW4gbWFudWFsbHkgY29weSBlYWNoIGNlbGwgb2YgZGF0YSwgaG93ZXZlciwgdGhpcyBwcm9jZXNzIGlzIG9mdGVuIGluZWZmaWNpZW50LCBzdWJqZWN0IHRvIGVycm9yLCBhbmQgbm90IHJlcHJvZHVjaWJsZS4gCgpXZSBjYW4gYWxzbyB1c2UgYFJgIGZvciB3ZWIgc2NyYXBpbmcuIAoKW1dlYiBzY3JhcGluZ10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvV2ViX3NjcmFwaW5nP29sZGZvcm1hdD10cnVlKXt0YXJnZXQ9Il9ibGFuayJ9IGlzIHRoZSBwcm9jZXNzIG9mIGV4dHJhY3RpbmcgZGF0YSBmcm9tIGEgd2Vic2l0ZS4KClRoZXJlIGFyZSB0d28gbWFpbiBzdGVwcyB0byB3ZWIgc2NyYXBpbmc6ICAKCjEuIElkZW50aWZ5IGxvY2F0aW9uIG9mIGRhdGEgdGhhdCB3aWxsIGJlIHNjcmFwZWQgIAoKMi4gU2F2ZSB0aGUgd2VicGFnZSBlbGVtZW50IHRvIGFuIG9iamVjdCAgCgpXZSBhY2NvbXBsaXNoIFNURVAgMSB3aXRoIG91ciB3ZWIgYnJvd3Nlci4KCldlIGFjY29tcGxpc2ggU1RFUCAyIGluIHRoZSBgUmAgcHJvZ3JhbW1pbmcgZW52aXJvbm1lbnQuIAoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKkkgY291bGQgbm90IGZpbmQgdGhlIGFuaW1hdGlvbiB0aGF0IEkgcmVmZXJyZWQgdG8gb24gc2V2ZXJhbCBvY2Nhc2lvbnMuKioKCioqSG93ZXZlciwgSSB3YXMgYWJsZSB0byBmaW5kIHRoZSBzb3VyY2VzIHRoYXQgSSBjb25zdWx0ZWQgdG8gY3JlYXRlIHRoZSB0aHJlZSBzdGVwIGBydmVzdGAgcHJvY2Vzcy4gVGhleSBhcmUgaW5jbHVkZWQgYmVsb3cqKgoKW1JTdHVkaW9dKGh0dHBzOi8vcnN0dWRpby1wdWJzLXN0YXRpYy5zMy5hbWF6b25hd3MuY29tLzI2NjQzMF9mM2ZkNDY2MGIyNzQ0NzUxYWIxNDRhYTEzMDc2OGEwNi5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9CgpbQmxvZ10oaHR0cDovL2Jsb2cuY29yeW5pc3Nlbi5jb20vMjAxNS8wMS91c2luZy1ydmVzdC10by1zY3JhcGUtaHRtbC10YWJsZS5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9Cgo8L2Rpdj4KClRoZSBgcnZlc3RgICBwYWNrYWdlIGNhbiBiZSB0aG91Z2h0IG9mIGFzIHRoZSBgcGRmdG9vbHNgIHBhY2thZ2UgZm9yIHdlYnNjcmFwaW5nLiBVcG9uIHB1bGxpbmcgdGhlIGRhdGEsIGFkZGl0aW9uYWwgd3JhbmdsaW5nIHdpbGwgbGlrZWx5IGJlIHJlcXVpcmVkOyBidXQgbGlrZSB0aGUgYHBkZnRvb2xzYCBwYWNrYWdlLCBgcnZlc3RgIHN0cmVhbWxpbmVzIHRoZSBleHRyYWN0aW9uIHByb2Nlc3MuICAKClRoZSB0d28gc3RlcHMgY2FuIGJlIGJyb2tlbiBkb3duIGV2ZW4gZnVydGhlcjogCgoxKSBJZGVudGlmeSBsb2NhdGlvbiBvZiBkYXRhIHRoYXQgd2lsbCBiZSBzY3JhcGVkCgorIHJpZ2h0LWNsaWNrIHRvIGluc3BlY3QgZWxlbWVudCAod2VicGFnZSkKKyBob3ZlciBwb2ludGVyIG92ZXIgY29tcG9uZW50cyBvZiBlbGVtZW50ICh3ZWJwYWdlKSB1bnRpbCB0aGUgZGF0YSBoYXMgYmVlbiBmb3VuZAorIGNvcHkgWHBhdGggb2YgZGF0YSBzb3VnaHQKCjMpIFNhdmUgd2VicGFnZSBlbGVtZW50IHRvIGFuIG9iamVjdAoKKyBpbXBvcnQgaHRtbCBjb2RlIGZvciBlbGVtZW50ICh3ZWJwYWdlKQorIGV4dHJhY3QgcGllY2VzICh0YWJsZSkgb3V0IG9mIEhUTUwgZG9jdW1lbnRzICh3ZWJwYWdlKSB1c2luZyBYcGF0aAorIHBhcnNlIHRoZSBodG1sIHRhYmxlIGludG8gYSBkYXRhIGZyYW1lCgpCZWxvdyBpcyBhIGFuaW1hdGVkIG92ZXJ2aWV3IG9mIHRoZSBwcm9jZXNzLgoKYGBge3IsIGV2YWw9RkFMU0UsIGVjaG89RkFMU0V9CnN0ZXAxIDwtIGltYWdlX3JlYWQoaGVyZSgid2VicGFnZV9zY3JlZW5zaG90LnBuZyIpKQpzdGVwMiA8LSBpbWFnZV9yZWFkKGhlcmUoInRhYmxlX3NjcmVlbnNob3RfaW5zcGVjdC5wbmciKSkKc3RlcDMgPC0gaW1hZ2VfcmVhZChoZXJlKCJ0YWJsZV9zY3JlZW5zaG90X2luc3BlY3RfdGFibGUucG5nIikpCnN0ZXA0IDwtIGltYWdlX3JlYWQoaGVyZSgidGFibGVfc2NyZWVuc2hvdF9pbnNwZWN0X3RhYmxlX3hwYXRoLnBuZyIpKQpzdGVwNSA8LSBpbWFnZV9yZWFkKGhlcmUoInRhYmxlX3NjcmVlbnNob3RfeHBhdGhfY29weV9yLnBuZyIpKQpzdGVwNV96b29tIDwtIGltYWdlX3JlYWQoaGVyZSgidGFibGVfc2NyZWVuc2hvdF94cGF0aF9jb3B5X3Jfem9vbS5wbmciKSkKCmltYWdlX2luZm8oc3RlcDVfem9vbSkKCnN0ZXA1X3pvb20gPC0gaW1hZ2VfYm9yZGVyKHN0ZXA1X3pvb20sICJ3aGl0ZSIsICIyODR4MzM0IikKCmltZyA8LSBjKHN0ZXAxLAogICAgICAgICBzdGVwMiwKICAgICAgICAgc3RlcDIsCiAgICAgICAgIHN0ZXAzLAogICAgICAgICBzdGVwMywKICAgICAgICAgc3RlcDQsCiAgICAgICAgIHN0ZXA0LAogICAgICAgICBzdGVwNSwKICAgICAgICAgc3RlcDUsCiAgICAgICAgIHN0ZXA1X3pvb20sCiAgICAgICAgIHN0ZXA1X3pvb20sCiAgICAgICAgIHN0ZXA1X3pvb20sCiAgICAgICAgIHN0ZXAxKQoKZWR1Y2F0aW9uYWxfZ2lmIDwtIGltYWdlX3Jlc2l6ZShpbWcsICcxNDQweDkwMCEnKSAlPiUKICBpbWFnZV9iYWNrZ3JvdW5kKCd3aGl0ZScpICU+JQogIGltYWdlX21vcnBoKGZyYW1lcyA9IDEwKSAlPiUKICBpbWFnZV9hbmltYXRlKGRlbGF5ID0gMjAsCiAgICAgICAgICAgICAgICBvcHRpbWl6ZSA9IFRSVUUpCgppbWFnZV93cml0ZShlZHVjYXRpb25hbF9naWYsICJlZHVjYXRpb25hbC5naWYiKQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLGV2YWw9RkFMU0V9CmltYWdlX3JlYWQoaGVyZSgiZWR1Y2F0aW9uYWwuZ2lmIikpCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CnN0ZXAxIDwtIGltYWdlX3JlYWQoaGVyZSgid2VicGFnZV9zY3JlZW5zaG90LnBuZyIpKQpzdGVwMiA8LSBpbWFnZV9yZWFkKGhlcmUoInRhYmxlX3NjcmVlbnNob3RfaW5zcGVjdC5wbmciKSkKc3RlcDMgPC0gaW1hZ2VfcmVhZChoZXJlKCJ0YWJsZV9zY3JlZW5zaG90X2luc3BlY3RfdGFibGUucG5nIikpCnN0ZXA0IDwtIGltYWdlX3JlYWQoaGVyZSgidGFibGVfc2NyZWVuc2hvdF9pbnNwZWN0X3RhYmxlX3hwYXRoLnBuZyIpKQpzdGVwNSA8LSBpbWFnZV9yZWFkKGhlcmUoInRhYmxlX3NjcmVlbnNob3RfeHBhdGhfY29weV9yLnBuZyIpKQpzdGVwNV96b29tIDwtIGltYWdlX3JlYWQoaGVyZSgidGFibGVfc2NyZWVuc2hvdF94cGF0aF9jb3B5X3Jfem9vbS5wbmciKSkKYGBgCgpbTGV0J3MgZ28gdG8gdGhlIHdlYiBwYWdlIHdpdGggYWxsIHRoZSB0YWJsZXMgd2UgYXJlIGludGVyZXN0ZWQgaW4gc2NyYXBpbmcuXShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0VGFic1NlY3QxMXBlMjAxOC5odG0pCgpgYGB7ciwgZWNobz1GQUxTRX0Kc3RlcDEKYGBgCgpPbmNlIG9uIHRoZSB3ZWJwYWdlLCB0aGVyZSBhcmVuJ3QgYW55IHZpc2libGUgb3B0aW9ucyB0byBkb3dubG9hZCB0aGUgZGF0YS4gCgpSaWdodC1jbGljayBhbmQgc2VsZWN0ICJJbnNwZWN0IiAKCmBgYHtyLCBlY2hvPUZBTFNFfQpzdGVwMgpgYGAKCkEgd2luZG93IG9wZW5zLiAKClRoaXMgd2luZG93IGFsbG93cyB1cyB0byBnbGFuY2UgYXQgdGhlIGludGVybmFsIG1lY2hhbmljcyBvZiB0aGUgd2VicGFnZS4gVG8gc2NyYXBlIHRoZSBkYXRhIGZyb20gdGhlIHdlYnBhZ2UsIHdlIG5lZWQgdG8gZmlyc3QgbGVhcm4gYSBsaXR0bGUgYml0IGFib3V0IHRoZSBjb21wb25lbnRzIHRoYXQgbWFrZSBpdCB0aGV0IHdlYiBwYWdlIGl0IGlzLiAKCkhvdmVyaW5nIG91ciBtb3VzZSBvdmVyIHRoZSBlbGVtZW50cyBvZiB0aGUgd2VicGFnZSBoaWdobGlnaHRzIHRoZSByZXNwZWN0aXZlIHNlY3Rpb24gb2YgdGhlIHdlYnBhZ2UgaXQgcmVwcmVzZW50cy4gQnkgaG92ZXJpbmcgb3ZlciBzZXZlcmFsIGVsZW1lbnRz4oCUYW5kIG9wZW5pbmcgZWxlbWVudHMgd2hlbiB0aGUgaGlnaGxpZ2h0ZWQgcG9ydGlvbiBpcyB0b28gbGFyZ2XigJR3ZSBjYW4gaW5kZW50aWZ5IHRoZSBlbGVtZW50IHRoYXQgY29udGFpbnMgdGhlIGRhdGEgd2UgYXJlIGxvb2tpbmcgZm9yLiAKCmBgYHtyLCBlY2hvPUZBTFNFfQpzdGVwMwpgYGAKClJpZ2h0IGNsaWNrIG9uIHRoZSBlbGVtZW50IGFuZCBjb3B5IHRoZSBYUGF0aC4gV2Ugd2lsbCBuZWVkIHRoaXMgWFBhdGggZm9yIHRoZSBuZXh0IHN0ZXAuCgpgYGB7ciwgZWNobz1GQUxTRX0Kc3RlcDQKYGBgCgpOb3cgd2UgY2FuIHJldHVybiB0byB0aGUgYFJgIHByb2dyYW1taW5nIGVudmlyb25tZW50CgpgYGB7ciwgZWNobz1GQUxTRX0Kc3RlcDUKYGBgCgo8c3R5bGU+CmRpdi5yZWQgeyBiYWNrZ3JvdW5kLWNvbG9yOiNGRkU2RTY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAicmVkIj4KCioqSSBpbmNsdWRlZCB0aGUgZm9sbG93aW5nIGxpbmUgdG8gaGVscCBzZXBhcmF0ZSB0aGUgcHJvY2Vzcy4qKgoKPC9kaXY+CgoqKioKCioqMikgU2F2ZSB3ZWJwYWdlIGVsZW1lbnQgdG8gYW4gb2JqZWN0KiogCgpGb3IgdGhlIGZpcnN0IHF1ZXN0aW9uIHdlIGludGVuZCB0byBhbnN3ZXIsIHRoZSBYUGF0aCBpcyBgL2h0bWwvYm9keS9kaXZbNF0vZGl2WzFdL3RhYmxlYC4gV2UgdXNlIHRoaXMgWHBhdGggd2l0aCBmdW5jdGlvbnMgZnJvbSB0aGUgYHJ2ZXN0YCBwYWNrYWdlIHRvIHNjcmFwZSBkYXRhIGZyb20gdGhlIHdlYi4KCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipJIHdhbnRlZCB0byBpbmNsdWRlIHRoZSBsYXN0IHNsaWRlL2NvbXBvbmVudCBvZiB0aGUgR0lGLiBIb3dldmVyLCBJIHJlYWxpemVkIHRoYXQgdGhlIGF1ZGllbmNlIHdvdWxkIGFsc28gYmVuZWZpdCBmcm9tIGhhdmluZyBhbiBhY3R1YWwgY29kZSBjaHVuay4gQXMgYSByZXN1bHQsIHRoaXMgc2VjdGlvbiBtYXkgbmVlZCBzb21lIHZlcnkgbWlub3IgcmV3b3JraW5nLioqCgo8L2Rpdj4KCmBgYHtyLCBlY2hvPUZBTFNFfQpzdGVwNV96b29tCmBgYAoKV2UgbmVlZCB0bzoKCisgaW1wb3J0IGh0bWwgY29kZSBmb3IgZWxlbWVudCAod2VicGFnZSkKKyBleHRyYWN0IHBpZWNlcyAodGFibGUpIG91dCBvZiBIVE1MIGRvY3VtZW50cyAod2VicGFnZSkgdXNpbmcgWHBhdGgKKyBwYXJzZSB0aGUgaHRtbCB0YWJsZSBpbnRvIGEgZGF0YSBmcmFtZQoKVG8gZG8gdGhpczoKCisgV2UgaW1wb3J0IHRoZSBodG1sIGNvZGUgdXNpbmcgYHJ2ZXN0OjpyZWFkX2h0bWwoKWAuCisgV2UgZXh0cmFjdCBzcGVjaWZpYyBjb21wb25lbnRzIG9mIHRoZSB3ZWJwYWdlIHVzaW5nIGBydmVzdDo6cmVhZF9ub2RlKClgLgorIFdlIGNvbnZlcnQgdGhpcyBodG1sIHRhYmxlIGludG8gYSBkYXRhZnJhbWUgdXNpbmcgYHJ2ZXN0OjpodG1sX3RhYmxlKClgLgoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKlRoZSBgcnZlc3RgIHBhY2thZ2UgcHJvdmlkZXMgd3JhcHBlcnMgZm9yIHRoZSBgeG1sMmAgYW5kIGBodHRyYCBwYWNrYWdlcy4gSSB3YXMgbm90IHN1cmUgd2hldGhlciB0byB0YWcgdGhlIGZvbGxvd2luZyBmdW5jdGlvbnMgYXMgcnZlc3Qgb3IgYHhtbDJgL2BodHRyYC4gSSB3aWxsIGxlYXZlIHRoYXQgZGVjaXNpb24gdG8geW91Li4qKgoKPC9kaXY+CgpgYGB7cn0KdXJsMTEuMWEgPC0gImh0dHBzOi8vd3d3LnNhbWhzYS5nb3YvZGF0YS9zaXRlcy9kZWZhdWx0L2ZpbGVzL2NiaHNxLXJlcG9ydHMvTlNEVUhEZXRhaWxlZFRhYnMyMDE4UjIvTlNEVUhEZXRUYWJzU2VjdDExcGUyMDE4Lmh0bSIKdGFibGUxMS4xYSA8LSB1cmwxMS4xYSAlPiUKICByZWFkX2h0bWwoKSAlPiUKICBodG1sX25vZGVzKHhwYXRoPScvaHRtbC9ib2R5L2Rpdls0XS9kaXZbMV0vdGFibGUnKSAlPiUKICBodG1sX3RhYmxlKCkKdGFibGUxMS4xYSA8LSB0YWJsZTExLjFhW1sxXV0KYGBgCgpHcmVhdCEgV2UgaGF2ZSBzdWNjZXNzZnVsbHkgc2NyYXBlZCB0aGUgZGF0YS4KCkZyb20gaGVyZSBvbiwgd2Ugd2lsbCBuZWVkIHRvIHdyYW5nbGUgdGhlIGRhdGEuCgpGaXJzdCwgd2UgbmVlZCB0byByZXBlYXQgdGhlIGFib3ZlIHByb2Nlc3MgZm9yIHRoZSBvdGhlciB0YWJsZXMgd2UgYXJlIGludGVyZXN0ZWQgaW4uIAoKV2UgY2FuIGNyZWF0ZSBhIGZ1bmN0aW9uIHRvIGFjY29tcGxpc2ggdGhpcyBzdWNjaW5jdGx5LiAKCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipGb3Igc29tZSBvZGQgcmVhc29uLCBjYWxsaW5nIHRoZSBgZnVuY3Rpb24oKWAgZnVuY3Rpb24gd2l0aCB0aGUgYGJhc2U6OmAgcHJlZml4IGNhdXNlcyBhbiBlcnJvci4qKgoKPC9kaXY+CgpgYGB7cn0Kc2NyYXBlciA8LSBmdW5jdGlvbihYUEFUSCl7CiAgdXJsIDwtICJodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0VGFic1NlY3QxMXBlMjAxOC5odG0iCiAgdGFibGUgPC0gdXJsICU+JQogIHJlYWRfaHRtbCgpICU+JQogIGh0bWxfbm9kZXMoeHBhdGg9WFBBVEgpICU+JQogIGh0bWxfdGFibGUoKQogIG91dHB1dCA8LSB0YWJsZVtbMV1dCiAgb3V0cHV0Cn0KYGBgCgpXZSBhcHBseSB0aGUgZnVuY3Rpb24gd2UgY3JlYXRlZCB0b28gdGhlIAoKYGBge3J9CnRhYmxlMTEuMWIgPC0gc2NyYXBlcihYUEFUSCA9ICIvaHRtbC9ib2R5L2Rpdls0XS9kaXZbMl0vdGFibGUiKQp0YWJsZTExLjJhIDwtIHNjcmFwZXIoWFBBVEggPSAnL2h0bWwvYm9keS9kaXZbNF0vZGl2WzNdL3RhYmxlJykKdGFibGUxMS4yYiA8LSBzY3JhcGVyKFhQQVRIID0gJy9odG1sL2JvZHkvZGl2WzRdL2Rpdls0XS90YWJsZScpCnRhYmxlMTEuM2EgPC0gc2NyYXBlcihYUEFUSCA9ICcvaHRtbC9ib2R5L2Rpdls0XS9kaXZbNV0vdGFibGUnKQp0YWJsZTExLjNiIDwtIHNjcmFwZXIoWFBBVEggPSAnL2h0bWwvYm9keS9kaXZbNF0vZGl2WzZdL3RhYmxlJykKdGFibGUxMS40YSA8LSBzY3JhcGVyKFhQQVRIID0gJy9odG1sL2JvZHkvZGl2WzRdL2Rpdls3XS90YWJsZScpCnRhYmxlMTEuNGIgPC0gc2NyYXBlcihYUEFUSCA9ICcvaHRtbC9ib2R5L2Rpdls0XS9kaXZbOF0vdGFibGUnKQpgYGAKCiMjICoqRGF0YSBFeHBsb3JhdGlvbiBhbmQgV3JhbmdsaW5nKioKKioqIAoKTm93IHRoYXQgd2UndmUgaW1wb3J0ZWQgdGhlIGRhdGEsIGxldCdzIHNlZSBpZiB3ZSBjYW4gd3JhbmdsZSBhIHRhYmxlLiBTaW5jZSB0aGUgZGF0YSBjb21lcyBmcm9tIGEgc291cmNlIHRoYXQgaXMgd2VsbC1tYWludGFpbmVkLCBpdCBpcyBsaWtlbHkgdGhhdCB3aGF0ZXZlciBzdGVwcyB3ZSB0YWtlIHRvIHdyYW5nbGUgdGhpcyBmaXJzdCB0YWJsZSB3aWxsIGFsc28gYmUgbmVjZXNzYXJ5IGluIHRoZSB3cmFuZ2xpbmcgb2Ygc3Vic2VxdWVudCB0YWJsZXMuIFRoaXMgaXMgYmVjYXVzZSB3ZWxsLW1haW50YWluZWQgZGF0YSBzb3VyY2VzIG9mdGVuIGZvcm1hdCBkaWZmZXJlbnQgZGF0YXNldHMgc2ltaWxhcmx5LiBXZSBjYW4gdGFrZSBhZHZhbnRhZ2Ugb2YgdGhpcyBzaW1pbGFyaXR5IHRvIHNwZWVkIHVwIHRoZSB3cmFuZ2xpbmcgcHJvY2Vzcy4gCgoqKlRhYmxlMTEuMWEqKgoKYGBge3J9CmJhc2U6OmRpbSh0YWJsZTExLjFhKQoKdGFibGUxMS4xYSA8LSB0YWJsZTExLjFhWy1kaW0odGFibGUxMS4xYSlbMV0sXQoKdGFibGUxMS4xYSA8LSB0YWJsZTExLjFhICU+JQogIGRwbHlyOjpuYV9pZigibmMiKSAlPiUKICBkcGx5cjo6bmFfaWYoIi0tIikgJT4lCiAgZHBseXI6Om5hX2lmKCIiKSAlPiUKICBkcGx5cjo6bmFfaWYoIioiKQoKdGFibGUxMS4xYSA8LSB0YWJsZTExLjFhICU+JQogIHRpYmJsZTo6YXNfdGliYmxlKCkgJT4lCiAgZHBseXI6OnJlbmFtZShNSFNfc2V0dGluZyA9IGBTZXR0aW5nIFdoZXJlIE1lbnRhbCBIZWFsdGggU2VydmljZVdhcyBSZWNlaXZlZGApCgpwYXJ0QSA8LSB0YWJsZTExLjFhICU+JQogIGRwbHlyOjpzZWxlY3QoTUhTX3NldHRpbmcpCgpwYXJ0QiA8LSB0YWJsZTExLjFhICU+JQogIHNlbGVjdCgtTUhTX3NldHRpbmcpCgpwYXJ0QSA8LSBwYXJ0QSAlPiUKICBkcGx5cjo6bXV0YXRlKE1IU19zZXR0aW5nID0gYmFzZTo6Z3N1YigiW1s6ZGlnaXQ6XV0rfFtcclxuXXxbWzpwdW5jdDpdXXwoW1s6Ymxhbms6XV0pXFwxKyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1IU19zZXR0aW5nKSkKCnBhcnRCIDwtIHBhcnRCICU+JQogIG11dGF0ZShkcGx5cjo6YWNyb3NzKC5jb2xzID0gZHBseXI6OmV2ZXJ5dGhpbmcoKSwKICAgICAgICAgICAgICAgIHN0cmluZ3I6OnN0cl9yZW1vdmVfYWxsLCAiYSIpKSAlPiUKICBtdXRhdGUoZHBseXI6OmFjcm9zcyguY29scyA9IGRwbHlyOjpldmVyeXRoaW5nKCksCiAgICAgICAgICAgICAgICBzdHJpbmdyOjpzdHJfcmVtb3ZlX2FsbCwgIiwiKSkKCmJhc2U6OnJtKHRhYmxlMTEuMWEpCgp0YWJsZTExLjFhIDwtIGRwbHlyOjpiaW5kX2NvbHMocGFydEEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJ0QikKCnRhYmxlMTEuMWEgPC0gdGFibGUxMS4xYSAlPiUKICB0aWR5cjo6cGl2b3RfbG9uZ2VyKGNvbHMgPSBkcGx5cjo6Y29udGFpbnMoIjIwIiksIG5hbWVzX3RvID0gIlllYXIiLCB2YWx1ZXNfdG8gPSAiTnVtYmVyIikKCnRhYmxlMTEuMWEgPC0gdGFibGUxMS4xYSAlPiUKICBkcGx5cjo6ZmlsdGVyKE1IU19zZXR0aW5nICE9ICJHZW5lcmFsIE1lZGljaW5lIikgJT4lCiAgZHBseXI6OmZpbHRlcihNSFNfc2V0dGluZyAhPSAiSnV2ZW5pbGUgSnVzdGljZSIpICNMZWFkaW5nIGxpbmVzIHdpdGggbm8gZGF0YQoKdGFibGUxMS4xYSA8LSB0YWJsZTExLjFhICU+JQogIG11dGF0ZShhY3Jvc3MoYyhZZWFyLCBOdW1iZXIpLCBhcy5udW1lcmljKSkKYGBgCgpXZSB3aWxsIHdyaXRlIGEgZnVuY3Rpb24gdG8gc2ltcGxpZnkgdGhpcyBwcm9jZXNzLgoKVGhlIGZ1bmN0aW9uIG5lZWRzIHRvOgoKLSByZW1vdmUgdGhlIGxhc3Qgcm93IG9mIHRoZSB0YWJsZQotIGdldCByaWQgb2YgY2VydGFpbiBwYXR0ZXJucwotIHRyYW5zaXRpb24gdGhlIGRhdGEgdG8gbG9uZyBmb3JtYXQKCmBgYHtyfQpkYXRhX3ByZXBfc2V0dGluZ3MgPC0gZnVuY3Rpb24oVEFCTEUsIG9sZF9jb2wsIG5ld19jb2wsIHBpdm90X2NvbCl7CiAgVEFCTEUgPC0gVEFCTEVbLWRpbShUQUJMRSlbMV0sXQogIFRBQkxFIDwtIFRBQkxFICU+JQogIG5hX2lmKCJuYyIpICU+JQogIG5hX2lmKCItLSIpICU+JQogIG5hX2lmKCIiKSAlPiUKICBuYV9pZigiKiIpCiAgVEFCTEUgPC0gVEFCTEUgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHJlbmFtZSh7e25ld19jb2x9fSA6PSB7e29sZF9jb2x9fSkKICBwYXJ0QSA8LSBUQUJMRSAlPiUKICAgIHNlbGVjdCh7e25ld19jb2x9fSkKICBwYXJ0QiA8LSBUQUJMRSAlPiUKICAgIHNlbGVjdCgte3tuZXdfY29sfX0pCiAgcGFydEEgPC0gcGFydEEgJT4lCiAgbXV0YXRlKHt7bmV3X2NvbH19IDo9IHBhcnRBICU+JQogICAgICAgICAgIHNlbGVjdCh7e25ld19jb2x9fSkgJT4lCiAgICAgICAgICAgZHBseXI6OnB1bGwoe3tuZXdfY29sfX0pICU+JQogICAgICAgICAgIGdzdWIoIltbOmRpZ2l0Ol1dK3xbXHJcbl18W1s6cHVuY3Q6XV18KFtbOmJsYW5rOl1dKVxcMSsiLAogICAgICAgICAgICAgICAgICAgICAgICAiIiwgLikpCiAgcGFydEIgPC0gcGFydEIgJT4lCiAgICBtdXRhdGUoYWNyb3NzKC5jb2xzID0gZXZlcnl0aGluZygpLAogICAgICAgICAgICAgICAgc3RyX3JlbW92ZV9hbGwsICJhIikpICU+JQogICAgbXV0YXRlKGFjcm9zcyguY29scyA9IGV2ZXJ5dGhpbmcoKSwKICAgICAgICAgICAgICAgIHN0cl9yZW1vdmVfYWxsLCAiLCIpKQogIHJtKFRBQkxFKQogIFRBQkxFIDwtIGJpbmRfY29scyhwYXJ0QSwKICAgICAgICAgICAgICAgICAgICAgcGFydEIpCiAgVEFCTEUgPC0gVEFCTEUgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjb250YWlucygiMjAiKSwgbmFtZXNfdG8gPSAiWWVhciIsIHZhbHVlc190byA9IHBpdm90X2NvbCkKICBUQUJMRQp9CmBgYAoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKkkgaW5jbHVkZWQgdGhlIGZvbGxvd2luZyBsaW5lIHRvIGhlbHAgc2VwYXJhdGUgdGhlIHRhYmxlcy4qKgoKPC9kaXY+CgoqKioKCioqVGFibGUxMS4xYSoqCgpXZSB0aGVuIGFwcGx5IHRoaXMgZnVuY3Rpb24gdG8gdGhlIHRhYmxlLCByaWRkaW5nIHRoZSB0YWJsZSBvZiBoZWFkaW5ncyBhbmQgZW5zdXJpbmcgc29tZSBvZiBvdXIgY29tbW9ucyBhcmUgY29ycmVjdGx5IG9mIG51bWVyaWMgY2xhc3MuCgpgYGB7cn0KZGltKHRhYmxlMTEuMWIpCgp0YWJsZTExLjFiIDwtIGRhdGFfcHJlcF9zZXR0aW5ncyhUQUJMRSA9IHRhYmxlMTEuMWIsCiAgICAgICAgICBvbGRfY29sID0gIlNldHRpbmcgV2hlcmUgTWVudGFsIEhlYWx0aCBTZXJ2aWNlV2FzIFJlY2VpdmVkIiwKICAgICAgICAgIG5ld19jb2wgPSAiTUhTX3NldHRpbmciLAogICAgICAgICAgcGl2b3RfY29sID0gIlBlcmNlbnQiKQoKdGFibGUxMS4xYiA8LSB0YWJsZTExLjFiICU+JQogIGZpbHRlcihNSFNfc2V0dGluZyAhPSAiR2VuZXJhbCBNZWRpY2luZSIpICU+JQogIGZpbHRlcihNSFNfc2V0dGluZyAhPSAiSnV2ZW5pbGUgSnVzdGljZSIpICNMZWFkaW5nIGxpbmVzIHdpdGggbm8gZGF0YQoKdGFibGUxMS4xYiA8LSB0YWJsZTExLjFiICU+JQogIG11dGF0ZShhY3Jvc3MoYyhZZWFyLCBQZXJjZW50KSwgYXMubnVtZXJpYykpCmBgYAoKV2Ugd3JpdGUgYSBmdW5jdGlvbiB0byBzaW1wbGlmeSB0aGlzIHByb2Nlc3MgZm9yIGRhdGEgdGhhdCB1c2VzIGRlbW9ncmFwaGljIGdyb3VwcyBhcyB1bml0cyBvZiBvYnNlcnZhdGlvbi4KClRoZSBmdW5jdGlvbiBuZWVkcyB0bzoKCi0gcmVtb3ZlIHRoZSBsYXN0IHJvdyBvZiB0aGUgdGFibGUKLSBnZXQgcmlkIG9mIGNlcnRhaW4gcGF0dGVybnMKLSB0cmFuc2l0aW9uIHRoZSBkYXRhIHRvIGxvbmcgZm9ybWF0CgpgYGB7cn0KZGF0YV9wcmVwX2RlbSA8LSBmdW5jdGlvbihUQUJMRSwgb2xkX2NvbCwgbmV3X2NvbCwgcGl2b3RfY29sKXsKICBUQUJMRSA8LSBUQUJMRVstZGltKFRBQkxFKVsxXSxdCiAgVEFCTEUgPC0gVEFCTEUgJT4lCiAgbmFfaWYoIm5jIikgJT4lCiAgbmFfaWYoIi0tIikgJT4lCiAgbmFfaWYoIiIpICU+JQogIG5hX2lmKCIqIikKICBUQUJMRSA8LSBUQUJMRSAlPiUKICAgIGFzX3RpYmJsZSgpICU+JQogICAgcmVuYW1lKHt7bmV3X2NvbH19IDo9IHt7b2xkX2NvbH19KQogIHBhcnRBIDwtIFRBQkxFICU+JQogICAgZHBseXI6OnNlbGVjdCh7e25ld19jb2x9fSkKICBwYXJ0QiA8LSBUQUJMRSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoLXt7bmV3X2NvbH19KQogIHBhcnRBIDwtIHBhcnRBICU+JQogIG11dGF0ZSh7e25ld19jb2x9fSA6PSBwYXJ0QSAlPiUKICAgICAgICAgICBkcGx5cjo6c2VsZWN0KHt7bmV3X2NvbH19KSAlPiUKICAgICAgICAgICBwdWxsKHt7bmV3X2NvbH19KSAlPiUKICAgICAgICAgICBnc3ViKCJbXHJcbl18W1s6cHVuY3Q6XV18KFtbOmJsYW5rOl1dKVxcMSsiLAogICAgICAgICAgICAgICAgICAgICAgICAiIiwgLikpCiAgcGFydEEgPC0gcGFydEEgJT4lCiAgbXV0YXRlKHt7bmV3X2NvbH19IDo9IGRwbHlyOjpjYXNlX3doZW4oc3RyaW5ncjo6c3RyX2RldGVjdCghIWJhc2U6OmFzLm5hbWUobmV3X2NvbCksIHBhdHRlcm4gPSAiMSIpIH4gYmFzZTo6cGFzdGUoIkFnZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5ncjo6c3RyX3N1YighIWJhc2U6OmFzLm5hbWUobmV3X2NvbCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydCA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQgPTIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3I6OnN0cl9zdWIoISFiYXNlOjphcy5uYW1lKG5ld19jb2wpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQgPSAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kID0gNCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwPSJfIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAhIWJhc2U6OmFzLm5hbWUobmV3X2NvbCkpKQogIHBhcnRCIDwtIHBhcnRCICU+JQogICAgbXV0YXRlKGFjcm9zcyguY29scyA9IGV2ZXJ5dGhpbmcoKSwKICAgICAgICAgICAgICAgIHN0cl9yZW1vdmVfYWxsLCAiYSIpKSAlPiUKICAgIG11dGF0ZShhY3Jvc3MoLmNvbHMgPSBldmVyeXRoaW5nKCksCiAgICAgICAgICAgICAgICBzdHJfcmVtb3ZlX2FsbCwgIiwiKSkKICBybShUQUJMRSkKICBUQUJMRSA8LSBiaW5kX2NvbHMocGFydEEsCiAgICAgICAgICAgICAgICAgICAgIHBhcnRCKQogIFRBQkxFIDwtIFRBQkxFICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gY29udGFpbnMoIjIwIiksIG5hbWVzX3RvID0gIlllYXIiLCB2YWx1ZXNfdG8gPSBwaXZvdF9jb2wpCiAgVEFCTEUKfQpgYGAKCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipJIGluY2x1ZGVkIHRoZSBmb2xsb3dpbmcgbGluZSB0byBoZWxwIHNlcGFyYXRlIHRoZSB0YWJsZXMuKioKCjwvZGl2PgoKKioqCgoqKlRhYmxlMTEuMmEqKgoKV2UgdXNlIHRoZSBwcm9kdWNlZCBmdW5jdGlvbiB0byB3cmFuZ2xlIHRoZSBuZXh0IHBhaXIgb2YgdGFibGVzLiAKCmBgYHtyfQpkaW0odGFibGUxMS4yYSkKCnRhYmxlMTEuMmEgPC0gZGF0YV9wcmVwX2RlbShUQUJMRSA9IHRhYmxlMTEuMmEsCiAgICAgICAgICBvbGRfY29sID0gIkRlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljIiwKICAgICAgICAgIG5ld19jb2wgPSAiRGVtb2dyYXBoaWMiLAogICAgICAgIHBpdm90X2NvbCA9ICJOdW1iZXIiKQoKdGFibGUxMS4yYSAlPiUKICBmaWx0ZXIoIWNvbXBsZXRlLmNhc2VzKC4pKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoRGVtb2dyYXBoaWMpICU+JQogIHRhbGx5KCkKCnRhYmxlMTEuMmEgPC0gdGFibGUxMS4yYSAlPiUKICBmaWx0ZXIoc3RhdHM6OmNvbXBsZXRlLmNhc2VzKC4pIHwgRGVtb2dyYXBoaWMgPT0gIkFJQU4iKQoKdGFibGUxMS4yYSA8LSB0YWJsZTExLjJhICU+JQogIG11dGF0ZShhY3Jvc3MoYyhZZWFyLCBOdW1iZXIpLCBhcy5udW1lcmljKSkKYGBgCgo8c3R5bGU+CmRpdi5yZWQgeyBiYWNrZ3JvdW5kLWNvbG9yOiNGRkU2RTY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAicmVkIj4KCioqSSBpbmNsdWRlZCB0aGUgZm9sbG93aW5nIGxpbmUgdG8gaGVscCBzZXBhcmF0ZSB0aGUgdGFibGVzLioqCgo8L2Rpdj4KCioqKgoKKipUYWJsZTExLjJiKioKCmBgYHtyfQpkaW0odGFibGUxMS4yYikKCnRhYmxlMTEuMmIgPC0gZGF0YV9wcmVwX2RlbShUQUJMRSA9IHRhYmxlMTEuMmIsCiAgICAgICAgICBvbGRfY29sID0gIkRlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljIiwKICAgICAgICAgIG5ld19jb2wgPSAiRGVtb2dyYXBoaWMiLAogICAgICAgICAgcGl2b3RfY29sID0gIlBlcmNlbnQiKQoKdGFibGUxMS4yYiAlPiUKICBmaWx0ZXIoIWNvbXBsZXRlLmNhc2VzKC4pKSAlPiUKICBncm91cF9ieShEZW1vZ3JhcGhpYykgJT4lCiAgdGFsbHkoKQoKdGFibGUxMS4yYiA8LSB0YWJsZTExLjJiICU+JQogIGZpbHRlcihjb21wbGV0ZS5jYXNlcyguKSB8IERlbW9ncmFwaGljID09ICJBSUFOIikKCnRhYmxlMTEuMmIgPC0gdGFibGUxMS4yYiAlPiUKICBtdXRhdGUoYWNyb3NzKGMoWWVhciwgUGVyY2VudCksIGFzLm51bWVyaWMpKQpgYGAKCldlIHJlcGVhdCB0aGlzIHByb2Nlc3MgZm9yIHRoZSByZW1haW5pbmcgdGFibGVzLgoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKkkgaW5jbHVkZWQgdGhlIGZvbGxvd2luZyBsaW5lIHRvIGhlbHAgc2VwYXJhdGUgdGhlIHRhYmxlcy4qKgoKPC9kaXY+CgoqKioKCioqVGFibGUgMTEuM2EqKgoKYGBge3J9CmRpbSh0YWJsZTExLjNhKQoKdGFibGUxMS4zYSA8LSBkYXRhX3ByZXBfZGVtKFRBQkxFID0gdGFibGUxMS4zYSwKICAgICAgICAgIG9sZF9jb2wgPSAiRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWMiLAogICAgICAgICAgbmV3X2NvbCA9ICJEZW1vZ3JhcGhpYyIsCiAgICAgICAgICBwaXZvdF9jb2wgPSAiTnVtYmVyIikKCnRhYmxlMTEuM2EgJT4lCiAgZmlsdGVyKCFjb21wbGV0ZS5jYXNlcyguKSkgJT4lCiAgZ3JvdXBfYnkoRGVtb2dyYXBoaWMpICU+JQogIHRhbGx5KCkKCnRhYmxlMTEuM2EgPC0gdGFibGUxMS4zYSAlPiUKICBmaWx0ZXIoY29tcGxldGUuY2FzZXMoLikgfCBEZW1vZ3JhcGhpYyA9PSAiQUlBTiIpCgp0YWJsZTExLjNhIDwtIHRhYmxlMTEuM2EgJT4lCiAgbXV0YXRlKGFjcm9zcyhjKFllYXIsIE51bWJlciksIGFzLm51bWVyaWMpKQpgYGAKCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipJIGluY2x1ZGVkIHRoZSBmb2xsb3dpbmcgbGluZSB0byBoZWxwIHNlcGFyYXRlIHRoZSB0YWJsZXMuKioKCjwvZGl2PgoKKioqCgoqKlRhYmxlIDExLjNiKioKCmBgYHtyfQpkaW0odGFibGUxMS4zYikKCnRhYmxlMTEuM2IgPC0gZGF0YV9wcmVwX2RlbShUQUJMRSA9IHRhYmxlMTEuM2IsCiAgICAgICAgICBvbGRfY29sID0gIkRlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljIiwKICAgICAgICAgIG5ld19jb2wgPSAiRGVtb2dyYXBoaWMiLAogICAgICAgICAgcGl2b3RfY29sID0gIlBlcmNlbnQiKQoKdGFibGUxMS4zYiAlPiUKICBmaWx0ZXIoIWNvbXBsZXRlLmNhc2VzKC4pKSAlPiUKICBncm91cF9ieShEZW1vZ3JhcGhpYykgJT4lCiAgdGFsbHkoKQoKdGFibGUxMS4zYiA8LSB0YWJsZTExLjNiICU+JQogIGZpbHRlcihjb21wbGV0ZS5jYXNlcyguKSB8IERlbW9ncmFwaGljID09ICJBSUFOIikKCnRhYmxlMTEuM2IgPC0gdGFibGUxMS4zYiAlPiUKICBtdXRhdGUoYWNyb3NzKGMoWWVhciwgUGVyY2VudCksIGFzLm51bWVyaWMpKQpgYGAKCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipJIGluY2x1ZGVkIHRoZSBmb2xsb3dpbmcgbGluZSB0byBoZWxwIHNlcGFyYXRlIHRoZSB0YWJsZXMuKioKCjwvZGl2PgoKKioqCgoqKlRhYmxlIDExLjRhKioKCmBgYHtyfQpkaW0odGFibGUxMS40YSkKCnRhYmxlMTEuNGEgPC0gZGF0YV9wcmVwX2RlbShUQUJMRSA9IHRhYmxlMTEuNGEsCiAgICAgICAgICBvbGRfY29sID0gIkRlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljIiwKICAgICAgICAgIG5ld19jb2wgPSAiRGVtb2dyYXBoaWMiLAogICAgICAgICAgcGl2b3RfY29sID0gIk51bWJlciIpCgp0YWJsZTExLjRhICU+JQogIGZpbHRlcighY29tcGxldGUuY2FzZXMoLikpICU+JQogIGdyb3VwX2J5KERlbW9ncmFwaGljKSAlPiUKICB0YWxseSgpCgp0YWJsZTExLjRhIDwtIHRhYmxlMTEuNGEgJT4lCiAgZmlsdGVyKGNvbXBsZXRlLmNhc2VzKC4pIHwgRGVtb2dyYXBoaWMgPT0gIkFJQU4iKQoKdGFibGUxMS40YSA8LSB0YWJsZTExLjRhICU+JQogIG11dGF0ZShhY3Jvc3MoYyhZZWFyLCBOdW1iZXIpLCBhcy5udW1lcmljKSkKYGBgCgo8c3R5bGU+CmRpdi5yZWQgeyBiYWNrZ3JvdW5kLWNvbG9yOiNGRkU2RTY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAicmVkIj4KCioqSSBpbmNsdWRlZCB0aGUgZm9sbG93aW5nIGxpbmUgdG8gaGVscCBzZXBhcmF0ZSB0aGUgdGFibGVzLioqCgo8L2Rpdj4KCioqKgoKKipUYWJsZSAxMS40YioqCgpgYGB7cn0KZGltKHRhYmxlMTEuNGIpCgp0YWJsZTExLjRiIDwtIGRhdGFfcHJlcF9kZW0oVEFCTEUgPSB0YWJsZTExLjRiLAogICAgICAgICAgb2xkX2NvbCA9ICJEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpYyIsCiAgICAgICAgICBuZXdfY29sID0gIkRlbW9ncmFwaGljIiwKICAgICAgICAgIHBpdm90X2NvbCA9ICJQZXJjZW50IikKCnRhYmxlMTEuNGIgJT4lCiAgZmlsdGVyKCFjb21wbGV0ZS5jYXNlcyguKSkgJT4lCiAgZ3JvdXBfYnkoRGVtb2dyYXBoaWMpICU+JQogIHRhbGx5KCkKCnRhYmxlMTEuNGIgPC0gdGFibGUxMS40YiAlPiUKICBmaWx0ZXIoY29tcGxldGUuY2FzZXMoLikgfCBEZW1vZ3JhcGhpYyA9PSAiQUlBTiIpCgp0YWJsZTExLjRiIDwtIHRhYmxlMTEuNGIgJT4lCiAgbXV0YXRlKGFjcm9zcyhjKFllYXIsIFBlcmNlbnQpLCBhcy5udW1lcmljKSkKYGBgCgpOb3cgdGhhdCB3ZSd2ZSB3cmFuZ2xlZCB0aGUgZGF0YSwgd2UgY2FuIGdvIGFoZWFkIGFuZCBwcm9jZWVkIHdpdGggb3VyIGFuYWx5c2lzLiAKCiMjICoqRGF0YSBBbmFseXNpcyoqCioqKiAKCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipJbiB0aGlzIHNlY3Rpb24sIHdlIG9ubHkgYW5hbHl6ZWQgZGF0YSBmcm9tIHRhYmxlcyAyLTQuIERhdGEgZnJvbSB0YWJsZSAxIGlzIHZlcnkgZGlmZmVyZW50IHRoYW4gZGF0YSBmcm9tIHRhYmxlcyAyLTQuIEZvciBleHBlZGllbmN5LCBJIGRpZCBub3QgaW5jbHVkZSBhbiBleGFtcGxlIHdpdGggZGF0YSBmcm9tZSB0YWJsZSAxLiBUaGUgZm9sbG93aW5nIGNvZGUsIGhvd2V2ZXIsIGNhbiBlYXNpbHkgYmUgcmVwdXJwb3NlZCB0byBhY2NvbXBsaXNoIHRoYXQgb25jZSBhIHNwZWNpZmljIGdyb3VwIGhhcyBiZWVuIGlkZW50aWZpZWQgdG8gY29uZHVjdCB0aGUgdGVzdCBvbi4qKgoKPC9kaXY+CgpXZSB3b3VsZCBsaWtlIHRvIGNvbmR1Y3QgYSBbY2hpLXNxdWFyZWQgdGVzdF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ2hpLXNxdWFyZWRfdGVzdD9vbGRmb3JtYXQ9dHJ1ZSkgZm9yIGluZGVwZW5kZW5jZS4gCgpUbyBjb25kdWN0IHRoaXMgc3RhdGlzdGljYWwgdGVzdCwgd2UgbmVlZCB0byBwcm9kdWNlIGEgMngyIHRhYmxlLgoKVGhlIGZvbGxvd2luZyBjb2RlIHN1YnNldHMgdGhlIGRhdGEgd2UgbmVlZCBhbmQgbWFrZXMgdGhlIG5lY2Vzc2FyeSBtYW5pcHVsYXRpb25zIHNvIHRoYXQgdGhlIHVuaXRzIG9mIG9ic2VydmF0aW9uIGFyZSBhcHByb3ByaWF0ZS4gCgpgYGB7cn0KY2hpX3NxdWFyZV8xMS4yYSA8LSB0YWJsZTExLjJhICU+JQogIGZpbHRlcihZZWFyICVpbiUgYygyMDA5LCAyMDE4KSkgJT4lCiAgZmlsdGVyKERlbW9ncmFwaGljICVpbiUgYygiTWFsZSIsIkZlbWFsZSIpKSAlPiUKICBtdXRhdGUoTnVtYmVyID0gTnVtYmVyICogMTAwMCkKYGBgCgpUaGUgcmVzdWx0aW5nIG9iamVjdCBpcyBzdGlsbCBpbiBsb25nIGZvcm1hdC4KCmBgYHtyfQpjaGlfc3F1YXJlXzExLjJhCmBgYAoKVG8gY29uZHVjdCBhIGNoaS1zcXVhcmVkIHRlc3QgZm9yIGluZGVwZW5jZSB3ZSB3aWxsIG5lZWQgYSBbY29udGluZ2VuY3kgdGFibGVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NvbnRpbmdlbmN5X3RhYmxlP29sZGZvcm1hdD10cnVlKS4gCgpBIGNvbnRpbmdlbmN5IHRhYmxlIGNhbiBiZSBwcm9kdWNlZCBmcm9tIGRhdGEgaW4gbG9uZyBmb3JtYXQgYnkgdHJhbnNmb3JtaW5nIHRoZSBkYXRhIHRvIHdpZGUgZm9ybWF0IGFuZCByZXB1cnBvc2luZyBzb21lIHZhbHVlcyBhcyByb3cgbmFtZXMuIAoKYGBge3J9CmNoaV9zcXVhcmVfMTEuMmEgPC0gY2hpX3NxdWFyZV8xMS4yYSAlPiUKICB0aWR5cjo6cGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IFllYXIsCiAgICAgICAgICAgICAgbmFtZXNfcHJlZml4ID0gIlllYXIiLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IE51bWJlcikgJT4lCiAgdGliYmxlOjpjb2x1bW5fdG9fcm93bmFtZXMoIkRlbW9ncmFwaGljIikKYGBgCgpUaGUgZmluYWwgb2JqZWN0IHNob3VsZCBsb29rIGxpa2UgdGhpcy4gCgpgYGB7cn0KY2hpX3NxdWFyZV8xMS4yYQpgYGAKClRoZSBjaGktc3F1YXJlZCB0ZXN0IGZvciBpbmRlcGVuZGVuY2UgY2FuIGJlIGNvbmR1Y3RlZCB1c2luZyB0aGUgYHN0YXRzOjpjaGlzcS50ZXN0KClgIGZ1bmN0aW9uLiAKCmBgYHtyfQpzdGF0czo6Y2hpc3EudGVzdChjaGlfc3F1YXJlXzExLjJhKQpgYGAKCldlIGNhbiByZXBlYXQgdGhpcyBwcm9jZXNzIGZvciB0aGUgcmVtYWluaW5nIHRhYmxlcy4KCmBgYHtyfQpjaGlfc3F1YXJlXzExLjNhIDwtIHRhYmxlMTEuM2EgJT4lCiAgZmlsdGVyKFllYXIgJWluJSBjKDIwMDksIDIwMTgpKSAlPiUKICBmaWx0ZXIoRGVtb2dyYXBoaWMgJWluJSBjKCJNYWxlIiwiRmVtYWxlIikpICU+JQogIG11dGF0ZShOdW1iZXIgPSBOdW1iZXIgKiAxMDAwKQoKY2hpX3NxdWFyZV8xMS4zYSA8LSBjaGlfc3F1YXJlXzExLjNhICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBZZWFyLAogICAgICAgICAgICAgIG5hbWVzX3ByZWZpeCA9ICJZZWFyIiwgCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBOdW1iZXIpICU+JQogIGNvbHVtbl90b19yb3duYW1lcygiRGVtb2dyYXBoaWMiKQoKY2hpX3NxdWFyZV8xMS4zYQpgYGAKCmBgYHtyfQpjaGlzcS50ZXN0KGNoaV9zcXVhcmVfMTEuM2EpCmBgYAoKYGBge3J9CmNoaV9zcXVhcmVfMTEuNGEgPC0gdGFibGUxMS40YSAlPiUKICBmaWx0ZXIoWWVhciAlaW4lIGMoMjAwOSwgMjAxOCkpICU+JQogIGZpbHRlcihEZW1vZ3JhcGhpYyAlaW4lIGMoIk1hbGUiLCJGZW1hbGUiKSkgJT4lCiAgbXV0YXRlKE51bWJlciA9IE51bWJlciAqIDEwMDApCgpjaGlfc3F1YXJlXzExLjRhIDwtIGNoaV9zcXVhcmVfMTEuNGEgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IFllYXIsCiAgICAgICAgICAgICAgbmFtZXNfcHJlZml4ID0gIlllYXIiLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IE51bWJlcikgJT4lCiAgY29sdW1uX3RvX3Jvd25hbWVzKCJEZW1vZ3JhcGhpYyIpCgpjaGlfc3F1YXJlXzExLjRhCmBgYAoKYGBge3J9CmNoaXNxLnRlc3QoY2hpX3NxdWFyZV8xMS40YSkKYGBgCgojIyAqKkRhdGEgVmlzdWFsaXphdGlvbioqCioqKiAKCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipUaGlzIGlzIHRoZSBpbnRlbnRpb25hbGx5IHRlcnJpYmxlIHBsb3QgdGhhdCByZXF1aXJlcyBmYWNldGluZy4qKgoKPC9kaXY+CgpgYGB7cn0KdGFibGUxMS4xYiAlPiUKICBnZ3Bsb3QyOjpnZ3Bsb3QoYWVzKHggPSBZZWFyLCB5ID0gUGVyY2VudCwgZ3JvdXAgPSBNSFNfc2V0dGluZykpICsKICBnZ3Bsb3QyOjpnZW9tX2xpbmUoKSArCiAgZ2dwbG90Mjo6c2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA5LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDIwMDksIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDIwMDksIDIwMTgpKSArCiAgZ2dwbG90Mjo6bGFicyh0aXRsZSA9ICJTZXR0aW5ncyBXaGVyZSBNZW50YWwgSGVhbHRoIFNlcnZpY2VzIFdlcmUgUmVjZWl2ZWQgaW4gUGFzdCBZZWFyXG5hbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTciLAogICAgICAgc3VidGl0bGUgPSAiUGVyY2VudGFnZXMsIDIwMDItMjAxOCIpCmBgYAoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKlRoZSBwbG90cyBiZWxvdyBuZWVkIHRvIGJlIGNvcnJlY3RseSBmYWNldGVkLiBLZWVwIGluIG1pbmQgdGhhdCB0YWJsZXMgMTEuMisgbXVzdCBiZSBmYWNldGVkIGJ5IGRlbW9ncmFwaGljIGdyb3VwIHR5cGUgYW5kIG5vdCBieSBzZXR0aW5nIHR5cGUuKioKCjwvZGl2PgoKYGBge3J9CnRhYmxlMTEuMWIgJT4lCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IFBlcmNlbnQsIGdyb3VwID0gTUhTX3NldHRpbmcpKSArCiAgZ2VvbV9saW5lKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwOSwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNlcSgyMDA5LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygyMDA5LCAyMDE4KSkgKwogIGxhYnModGl0bGUgPSAiU2V0dGluZ3MgV2hlcmUgTWVudGFsIEhlYWx0aCBTZXJ2aWNlcyBXZXJlIFJlY2VpdmVkIGluIFBhc3QgWWVhclxuYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3IiwKICAgICAgIHN1YnRpdGxlID0gIlBlcmNlbnRhZ2VzLCAyMDAyLTIwMTgiKQpgYGAKCmBgYHtyfQp0YWJsZTExLjJiICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBQZXJjZW50LCBncm91cCA9IERlbW9ncmFwaGljKSkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDksIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwOSwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwOSwgMjAxOCkpICsKICBsYWJzKHRpdGxlID0gIk1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXJcbmFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNyIsCiAgICAgICBzdWJ0aXRsZSA9ICJCeSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3MsIFBlcmNlbnRhZ2VzLCAyMDA0LTIwMTgiKQpgYGAKCmBgYHtyfQp0YWJsZTExLjNiICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBQZXJjZW50LCBncm91cCA9IERlbW9ncmFwaGljKSkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDksIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwOSwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwOSwgMjAxOCkpICsKICBsYWJzKHRpdGxlID0gIk1ham9yIERlcHJlc3NpdmUgRXBpc29kZSB3aXRoIFNldmVyZSBJbXBhaXJtZW50IGluIFBhc3QgWWVhclxuYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3IiwKICAgICAgIHN1YnRpdGxlID0gIkJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogUGVyY2VudGFnZXMsIDIwMDYtMjAxOCIpCmBgYAoKYGBge3J9CnRhYmxlMTEuNGIgJT4lCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IFBlcmNlbnQsIGdyb3VwID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9saW5lKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwOSwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNlcSgyMDA5LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygyMDA5LCAyMDE4KSkgKyAKICBsYWJzKHRpdGxlID0gIlJlY2VpcHQgb2YgVHJlYXRtZW50IGZvciBEZXByZXNzaW9uIGluIFBhc3QgWWVhciBhbW9uZ1xuUGVyc29ucyBBZ2VkIDEyIHRvIDE3IHdpdGggTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIFBhc3QgWWVhciIsCiAgICAgICBzdWJ0aXRsZSA9ICJCeSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3M6IFBlcmNlbnRhZ2VzLCAyMDA0LTIwMTgiKQpgYGAKCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipUaGUgcGxvdHMgY3JlYXRlZCAoYWZ0ZXIgZmFjZXRpbmcgcHJvcGVybHkpIGNhbiBiZSB1c2VkIHRvIGFuc3dlciB0aGUgcXVlc3Rpb25zIGxpc3RlZCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBjYXNlIHN0dWR5LiBBZnRlciBmaW5hbGl6aW5nIHRoZSBwbG90cywgc29tZSB0aW1lIHNob3VsZCBiZSBzcGVudCB0b3dhcmRzIGZyYW1pbmcgdGhlIHZpc3VhbGl6YXRpb25zIGluIHN1Y2ggYSB3YXkgdG8gdW5kZXJzY29yZSBob3cgdGhleSB3ZXJlIHVzZWQgdG8gYXNud2VyIHRoZSBxdWVzdGlvbi4qKgoKPC9kaXY+CgojIyAqKlN1bW1hcnkqKgoqKiogCgojIyAqKlN1Z2dlc3RlZCBIb21ld29yayoqCioqKiAKCiMjICoqQWRkaXRpb25hbCBJbmZvcm1hdGlvbioqCioqKgoKIyMjIEhlbHBmdWwgTGlua3MKCgoqKlRoaXMgbmVlZHMgdG8gYmUgdXBkYXRlZCoqCgpbZ3VpZGVdKGh0dHBzOi8vYnJpYXR0ZS5naXRodWIuaW8vZ2djb3JyLykgZm9yIHVzaW5nIEdHYWxseSB0byBjcmVhdGUgY29ycmVsYXRpb24gcGxvdHMKCjx1PlRlcm1zIGFuZCBjb25jZXB0cyBjb3ZlcmVkOjwvdT4gIAoKW1RpZHl2ZXJzZV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gIApbUlN0dWRpbyBjaGVhdHNoZWV0c10oaHR0cHM6Ly9yc3R1ZGlvLmNvbS9yZXNvdXJjZXMvY2hlYXRzaGVldHMvKXt0YXJnZXQ9Il9ibGFuayJ9ICAKCjx1PlBhY2thZ2VzIHVzZWQgaW4gdGhpcyBjYXNlIHN0dWR5OiA8L3U+CgogUGFja2FnZSAgIHwgVXNlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAotLS0tLS0tLS0tIHwtLS0tLS0tLS0tLS0tCltoZXJlXShodHRwczovL2dpdGh1Yi5jb20vamVubnliYy9oZXJlX2hlcmUpe3RhcmdldD0iX2JsYW5rIn0gICAgICAgfCB0byBlYXNpbHkgbG9hZCBhbmQgc2F2ZSBkYXRhIApbdGlkeXZlcnNlXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgUiBwYWNrYWdlcyBmb3IgZGF0YSBzY2llbmNlCltydmVzdF0oaHR0cHM6Ly9naXRodWIuY29tL3RpZHl2ZXJzZS9ydmVzdCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gc2NyYXBlIHdlYiBwYWdlcwoKCiMjIyBBY2tub3dsZWRnZW1lbnRzCgpXZSB3b3VsZCBsaWtlIHRvIGFja25vd2xlZGdlIFtUYW1hciBNZW5kZWxzb25dKGh0dHBzOi8vd3d3Lmpoc3BoLmVkdS9mYWN1bHR5L2RpcmVjdG9yeS9wcm9maWxlLzE3NzAvdGFtYXItbWVuZGVsc29uKSBmb3IgYXNzaXN0aW5nIGluIGZyYW1pbmcgdGhlIG1ham9yIGRpcmVjdGlvbiBvZiB0aGUgY2FzZSBzdHVkeS4KCldlIHdvdWxkIGFsc28gbGlrZSB0byBhY2tub3dsZWRnZSB0aGUgW0Jsb29tYmVyZyBBbWVyaWNhbiBIZWFsdGggSW5pdGlhdGl2ZV0oaHR0cHM6Ly9hbWVyaWNhbmhlYWx0aC5qaHUuZWR1LykgZm9yIGZ1bmRpbmcgdGhpcyB3b3JrLiAKCgojIyMgKipSQSBOb3RlcyoqCgpbVGhpcyBpcyB0aGUgbW90aXZhdGluZyBhcnRpY2xlIGZvciB0aGlzIGNhc2Ugc3R1ZHldKGh0dHBzOi8vcHVibWVkLm5jYmkubmxtLm5paC5nb3YvMzA4Njk5MjcvKS4gSW4gdGhpcyBhcnRpY2xlLCB0aGV5IHdlYiBzY3JhcGUgdG8gb2J0YWluIHRoZSBkYXRhIHRoZXkgbmVlZC4gCgpbSGVyZSBpcyB0aGUgTGllYmVyIEluc3RpdHV0ZSdzIHJlc291cmNlIG9uIHdlYiBzY3JhcGVdKGh0dHA6Ly9yZXNlYXJjaC5saWJkLm9yZy9yc3RhdHNjbHViL3Bvc3QvaW50cm9kdWN0aW9uLXRvLXNjcmFwaW5nLWFuZC13cmFuZ2luZy10YWJsZXMtZnJvbS1yZXNlYXJjaC1hcnRpY2xlcy8jLlh3ODc4Wk5LaFFKKQoKW0hlcmUgaXMgYSByZXNvdWNlIHRoZSBMaWViZXIgSW5zdGl0dXRlIHNvdXJjZSBhYm92ZSByZWZlcnNlIHRvXShodHRwOi8vYmxvZy5jb3J5bmlzc2VuLmNvbS8yMDE1LzAxL3VzaW5nLXJ2ZXN0LXRvLXNjcmFwZS1odG1sLXRhYmxlLmh0bWwpCgpbSGVyZSBhcyBhIGdvb2QgcmVzb3VyY2UgdG8gbGVhcm4gaG93IHRvIHdlYiBzY3JhcGVdKGh0dHBzOi8vcnN0dWRpby1wdWJzLXN0YXRpYy5zMy5hbWF6b25hd3MuY29tLzI2NjQzMF9mM2ZkNDY2MGIyNzQ0NzUxYWIxNDRhYTEzMDc2OGEwNi5odG1sKQoKW1RoaXMgaXMgdGhlIHNldCBvZiB0YWJsZXMgd2Ugd291bGQgbGlrZSB0byBjb25zaWRlcl0oaHR0cHM6Ly93d3cuc2FtaHNhLmdvdi9kYXRhL3NpdGVzL2RlZmF1bHQvZmlsZXMvY2Joc3EtcmVwb3J0cy9OU0RVSERldGFpbGVkVGFiczIwMThSMi9OU0RVSERldFRhYnNTZWN0MTFwZTIwMTguaHRtKQo=